diff options
16 files changed, 698 insertions, 2655 deletions
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 1258509570..26834ebeb3 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -316,7 +316,7 @@ void Layer::onRemovedFromCurrentState() { void Layer::addToCurrentState() { if (mRemovedFromDrawingState) { mRemovedFromDrawingState = false; - mFlinger->mScheduler->registerLayer(this); + mFlinger->mScheduler->registerLayer(this, FrameRateCompatibility::Default); mFlinger->removeFromOffscreenLayers(this); } @@ -1100,42 +1100,6 @@ bool Layer::setDimmingEnabled(const bool dimmingEnabled) { return true; } -bool Layer::setFrameRateSelectionPriority(int32_t priority) { - if (mDrawingState.frameRateSelectionPriority == priority) return false; - mDrawingState.frameRateSelectionPriority = priority; - mDrawingState.sequence++; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - return true; -} - -int32_t Layer::getFrameRateSelectionPriority() const { - // Check if layer has priority set. - if (mDrawingState.frameRateSelectionPriority != PRIORITY_UNSET) { - return mDrawingState.frameRateSelectionPriority; - } - // If not, search whether its parents have it set. - sp<Layer> parent = getParent(); - if (parent != nullptr) { - return parent->getFrameRateSelectionPriority(); - } - - return Layer::PRIORITY_UNSET; -} - -bool Layer::setDefaultFrameRateCompatibility(FrameRateCompatibility compatibility) { - if (mDrawingState.defaultFrameRateCompatibility == compatibility) return false; - mDrawingState.defaultFrameRateCompatibility = compatibility; - mDrawingState.modified = true; - mFlinger->mScheduler->setDefaultFrameRateCompatibility(sequence, compatibility); - setTransactionFlags(eTransactionNeeded); - return true; -} - -scheduler::FrameRateCompatibility Layer::getDefaultFrameRateCompatibility() const { - return mDrawingState.defaultFrameRateCompatibility; -} - bool Layer::isLayerFocusedBasedOnPriority(int32_t priority) { return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE; }; @@ -1202,117 +1166,6 @@ StretchEffect Layer::getStretchEffect() const { return StretchEffect{}; } -bool Layer::propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren, - bool* transactionNeeded) { - // Gets the frame rate to propagate to children. - const auto frameRate = [&] { - if (overrideChildren && parentFrameRate.isValid()) { - return parentFrameRate; - } - - if (mDrawingState.frameRate.isValid()) { - return mDrawingState.frameRate; - } - - return parentFrameRate; - }(); - - auto now = systemTime(); - *transactionNeeded |= setFrameRateForLayerTreeLegacy(frameRate, now); - - // The frame rate is propagated to the children by default, but some properties may override it. - bool childrenHaveFrameRate = false; - const bool overrideChildrenFrameRate = overrideChildren || shouldOverrideChildrenFrameRate(); - const bool canPropagateFrameRate = shouldPropagateFrameRate() || overrideChildrenFrameRate; - for (const sp<Layer>& child : mCurrentChildren) { - childrenHaveFrameRate |= - child->propagateFrameRateForLayerTree(canPropagateFrameRate ? frameRate - : FrameRate(), - overrideChildrenFrameRate, transactionNeeded); - } - - // If we don't have a valid frame rate specification, but the children do, we set this - // layer as NoVote to allow the children to control the refresh rate - if (!frameRate.isValid() && childrenHaveFrameRate) { - *transactionNeeded |= - setFrameRateForLayerTreeLegacy(FrameRate(Fps(), FrameRateCompatibility::NoVote), - now); - } - - // We return whether this layer or its children has a vote. We ignore ExactOrMultiple votes for - // the same reason we are allowing touch boost for those layers. See - // RefreshRateSelector::rankFrameRates for details. - const auto layerVotedWithDefaultCompatibility = - frameRate.vote.rate.isValid() && frameRate.vote.type == FrameRateCompatibility::Default; - const auto layerVotedWithNoVote = frameRate.vote.type == FrameRateCompatibility::NoVote; - const auto layerVotedWithCategory = frameRate.category != FrameRateCategory::Default; - const auto layerVotedWithExactCompatibility = - frameRate.vote.rate.isValid() && frameRate.vote.type == FrameRateCompatibility::Exact; - return layerVotedWithDefaultCompatibility || layerVotedWithNoVote || layerVotedWithCategory || - layerVotedWithExactCompatibility || childrenHaveFrameRate; -} - -void Layer::updateTreeHasFrameRateVote() { - const auto root = [&]() -> sp<Layer> { - sp<Layer> layer = sp<Layer>::fromExisting(this); - while (auto parent = layer->getParent()) { - layer = parent; - } - return layer; - }(); - - bool transactionNeeded = false; - root->propagateFrameRateForLayerTree({}, false, &transactionNeeded); - - // TODO(b/195668952): we probably don't need eTraversalNeeded here - if (transactionNeeded) { - mFlinger->setTransactionFlags(eTraversalNeeded); - } -} - -bool Layer::setFrameRate(FrameRate::FrameRateVote frameRateVote) { - if (mDrawingState.frameRate.vote == frameRateVote) { - return false; - } - - mDrawingState.sequence++; - mDrawingState.frameRate.vote = frameRateVote; - mDrawingState.modified = true; - - updateTreeHasFrameRateVote(); - - setTransactionFlags(eTransactionNeeded); - return true; -} - -bool Layer::setFrameRateCategory(FrameRateCategory category, bool smoothSwitchOnly) { - if (mDrawingState.frameRate.category == category && - mDrawingState.frameRate.categorySmoothSwitchOnly == smoothSwitchOnly) { - return false; - } - - mDrawingState.sequence++; - mDrawingState.frameRate.category = category; - mDrawingState.frameRate.categorySmoothSwitchOnly = smoothSwitchOnly; - mDrawingState.modified = true; - - updateTreeHasFrameRateVote(); - - setTransactionFlags(eTransactionNeeded); - return true; -} - -bool Layer::setFrameRateSelectionStrategy(FrameRateSelectionStrategy strategy) { - if (mDrawingState.frameRateSelectionStrategy == strategy) return false; - mDrawingState.frameRateSelectionStrategy = strategy; - mDrawingState.sequence++; - mDrawingState.modified = true; - - updateTreeHasFrameRateVote(); - setTransactionFlags(eTransactionNeeded); - return true; -} - void Layer::setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime, gui::GameMode gameMode) { mDrawingState.postTime = postTime; @@ -1446,25 +1299,6 @@ void Layer::setFrameTimelineVsyncForSkippedFrames(const FrameTimelineInfo& info, addSurfaceFrameDroppedForBuffer(surfaceFrame, postTime); } -bool Layer::setFrameRateForLayerTreeLegacy(FrameRate frameRate, nsecs_t now) { - if (mDrawingState.frameRateForLayerTree == frameRate) { - return false; - } - - mDrawingState.frameRateForLayerTree = frameRate; - - // TODO(b/195668952): we probably don't need to dirty visible regions here - // or even store frameRateForLayerTree in mDrawingState - mDrawingState.sequence++; - mDrawingState.modified = true; - setTransactionFlags(eTransactionNeeded); - - mFlinger->mScheduler - ->recordLayerHistory(sequence, getLayerProps(), now, now, - scheduler::LayerHistory::LayerUpdateType::SetFrameRate); - return true; -} - bool Layer::setFrameRateForLayerTree(FrameRate frameRate, const scheduler::LayerProps& layerProps, nsecs_t now) { if (mDrawingState.frameRateForLayerTree == frameRate) { @@ -1543,57 +1377,6 @@ void Layer::miniDumpHeader(std::string& result) { result.append("\n"); } -void Layer::miniDumpLegacy(std::string& result, const DisplayDevice& display) const { - const auto outputLayer = findOutputLayerForDisplay(&display); - if (!outputLayer) { - return; - } - - std::string name; - if (mName.length() > 77) { - std::string shortened; - shortened.append(mName, 0, 36); - shortened.append("[...]"); - shortened.append(mName, mName.length() - 36); - name = std::move(shortened); - } else { - name = mName; - } - - StringAppendF(&result, " %s\n", name.c_str()); - - const State& layerState(getDrawingState()); - const auto& outputLayerState = outputLayer->getState(); - - if (layerState.zOrderRelativeOf != nullptr || mDrawingParent != nullptr) { - StringAppendF(&result, " rel %6d | ", layerState.z); - } else { - StringAppendF(&result, " %10d | ", layerState.z); - } - StringAppendF(&result, " %10d | ", mWindowType); - StringAppendF(&result, "%10s | ", toString(getCompositionType(display)).c_str()); - StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str()); - const Rect& frame = outputLayerState.displayFrame; - StringAppendF(&result, "%4d %4d %4d %4d | ", frame.left, frame.top, frame.right, frame.bottom); - const FloatRect& crop = outputLayerState.sourceCrop; - StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right, - crop.bottom); - const auto frameRate = getFrameRateForLayerTree(); - if (frameRate.vote.rate.isValid() || frameRate.vote.type != FrameRateCompatibility::Default) { - StringAppendF(&result, "%s %15s %17s", to_string(frameRate.vote.rate).c_str(), - ftl::enum_string(frameRate.vote.type).c_str(), - ftl::enum_string(frameRate.vote.seamlessness).c_str()); - } else { - result.append(41, ' '); - } - - const auto focused = isLayerFocusedBasedOnPriority(getFrameRateSelectionPriority()); - StringAppendF(&result, " [%s]\n", focused ? "*" : " "); - - result.append(kDumpTableRowLength, '-'); - result.append("\n"); -} - void Layer::miniDump(std::string& result, const frontend::LayerSnapshot& snapshot, const DisplayDevice& display) const { const auto outputLayer = findOutputLayerForDisplay(&display, snapshot.path); @@ -1679,7 +1462,6 @@ void Layer::addChild(const sp<Layer>& layer) { mCurrentChildren.add(layer); layer->setParent(sp<Layer>::fromExisting(this)); - updateTreeHasFrameRateVote(); } ssize_t Layer::removeChild(const sp<Layer>& layer) { @@ -1689,9 +1471,6 @@ ssize_t Layer::removeChild(const sp<Layer>& layer) { layer->setParent(nullptr); const auto removeResult = mCurrentChildren.remove(layer); - updateTreeHasFrameRateVote(); - layer->updateTreeHasFrameRateVote(); - return removeResult; } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index c838b97749..948c62df3c 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -330,18 +330,10 @@ public: REQUIRES(mFlinger->mStateLock); virtual bool setColorSpaceAgnostic(const bool agnostic); virtual bool setDimmingEnabled(const bool dimmingEnabled); - virtual bool setDefaultFrameRateCompatibility(FrameRateCompatibility compatibility); - virtual bool setFrameRateSelectionPriority(int32_t priority); virtual bool setFixedTransformHint(ui::Transform::RotationFlags fixedTransformHint); void setAutoRefresh(bool /* autoRefresh */); bool setDropInputMode(gui::DropInputMode); - // If the variable is not set on the layer, it traverses up the tree to inherit the frame - // rate priority from its parent. - virtual int32_t getFrameRateSelectionPriority() const; - // - virtual FrameRateCompatibility getDefaultFrameRateCompatibility() const; - // ui::Dataspace getDataSpace() const; virtual bool isFrontBuffered() const; @@ -702,7 +694,6 @@ public: inline const State& getDrawingState() const { return mDrawingState; } inline State& getDrawingState() { return mDrawingState; } - void miniDumpLegacy(std::string& result, const DisplayDevice&) const; void miniDump(std::string& result, const frontend::LayerSnapshot&, const DisplayDevice&) const; void dumpFrameStats(std::string& result) const; void dumpOffscreenDebugInfo(std::string& result) const; @@ -789,11 +780,6 @@ public: */ Rect getCroppedBufferSize(const Layer::State& s) const; - bool setFrameRate(FrameRate::FrameRateVote); - bool setFrameRateCategory(FrameRateCategory, bool smoothSwitchOnly); - - bool setFrameRateSelectionStrategy(FrameRateSelectionStrategy); - virtual void setFrameTimelineInfoForBuffer(const FrameTimelineInfo& /*info*/) {} void setFrameTimelineVsyncForBufferTransaction(const FrameTimelineInfo& info, nsecs_t postTime, gui::GameMode gameMode); @@ -905,19 +891,9 @@ public: void callReleaseBufferCallback(const sp<ITransactionCompletedListener>& listener, const sp<GraphicBuffer>& buffer, uint64_t framenumber, const sp<Fence>& releaseFence); - bool setFrameRateForLayerTreeLegacy(FrameRate, nsecs_t now); bool setFrameRateForLayerTree(FrameRate, const scheduler::LayerProps&, nsecs_t now); void recordLayerHistoryBufferUpdate(const scheduler::LayerProps&, nsecs_t now); void recordLayerHistoryAnimationTx(const scheduler::LayerProps&, nsecs_t now); - auto getLayerProps() const { - return scheduler::LayerProps{.visible = isVisible(), - .bounds = getBounds(), - .transform = getTransform(), - .setFrameRateVote = getFrameRateForLayerTree(), - .frameRateSelectionPriority = getFrameRateSelectionPriority(), - .isSmallDirty = mSmallDirty, - .isFrontBuffered = isFrontBuffered()}; - }; bool hasBuffer() const { return mBufferInfo.mBuffer != nullptr; } void setTransformHint(std::optional<ui::Transform::RotationFlags> transformHint) { mTransformHint = transformHint; @@ -1128,7 +1104,6 @@ private: LayerVector makeChildrenTraversalList(LayerVector::StateSet, const std::vector<Layer*>& layersInTree); - void updateTreeHasFrameRateVote(); bool propagateFrameRateForLayerTree(FrameRate parentFrameRate, bool overrideChildren, bool* transactionNeeded); void setZOrderRelativeOf(const wp<Layer>& relativeOf); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 4fd4c0ecc3..64b85c080e 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -109,12 +109,12 @@ LayerHistory::LayerHistory() LayerHistory::~LayerHistory() = default; -void LayerHistory::registerLayer(Layer* layer, bool contentDetectionEnabled) { +void LayerHistory::registerLayer(Layer* layer, bool contentDetectionEnabled, + FrameRateCompatibility frameRateCompatibility) { std::lock_guard lock(mLock); LOG_ALWAYS_FATAL_IF(findLayer(layer->getSequence()).first != LayerStatus::NotFound, "%s already registered", layer->getName().c_str()); - LayerVoteType type = - getVoteType(layer->getDefaultFrameRateCompatibility(), contentDetectionEnabled); + LayerVoteType type = getVoteType(frameRateCompatibility, contentDetectionEnabled); auto info = std::make_unique<LayerInfo>(layer->getName(), layer->getOwnerUid(), type); // The layer can be placed on either map, it is assumed that partitionLayers() will be called diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index c09f148a9b..e3babbabef 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -51,7 +51,8 @@ public: ~LayerHistory(); // Layers are unregistered when the weak reference expires. - void registerLayer(Layer*, bool contentDetectionEnabled); + void registerLayer(Layer*, bool contentDetectionEnabled, + FrameRateCompatibility frameRateCompatibility); // Sets the display size. Client is responsible for synchronization. void setDisplayArea(uint32_t displayArea) { mDisplayArea = displayArea; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 0cf7bdcc4e..799bc6d1c0 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -659,11 +659,12 @@ void Scheduler::addPresentFence(PhysicalDisplayId id, std::shared_ptr<FenceTime> } } -void Scheduler::registerLayer(Layer* layer) { +void Scheduler::registerLayer(Layer* layer, FrameRateCompatibility frameRateCompatibility) { // If the content detection feature is off, we still keep the layer history, // since we use it for other features (like Frame Rate API), so layers // still need to be registered. - mLayerHistory.registerLayer(layer, mFeatures.test(Feature::kContentDetection)); + mLayerHistory.registerLayer(layer, mFeatures.test(Feature::kContentDetection), + frameRateCompatibility); } void Scheduler::deregisterLayer(Layer* layer) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 94583db5a8..b7b5812fe5 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -222,7 +222,7 @@ public: REQUIRES(kMainThreadContext); // Layers are registered on creation, and unregistered when the weak reference expires. - void registerLayer(Layer*); + void registerLayer(Layer*, FrameRateCompatibility); void recordLayerHistory(int32_t id, const LayerProps& layerProps, nsecs_t presentTime, nsecs_t now, LayerHistory::LayerUpdateType) EXCLUDES(mDisplayLock); void setModeChangePending(bool pending); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 18d5bd50b3..c34d58ca65 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -8096,7 +8096,7 @@ status_t SurfaceFlinger::getDesiredDisplayModeSpecs(const sp<IBinder>& displayTo void SurfaceFlinger::onLayerFirstRef(Layer* layer) { mNumLayers++; if (!layer->isRemovedFromCurrentState()) { - mScheduler->registerLayer(layer); + mScheduler->registerLayer(layer, scheduler::FrameRateCompatibility::Default); } } diff --git a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h index 8b9d14b8f9..3104dd4720 100644 --- a/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h +++ b/services/surfaceflinger/tests/common/LayerLifecycleManagerHelper.h @@ -25,6 +25,7 @@ #include <FrontEnd/LayerHierarchy.h> #include <FrontEnd/LayerLifecycleManager.h> #include <FrontEnd/LayerSnapshotBuilder.h> +#include <Layer.h> // needed for framerate namespace android::surfaceflinger::frontend { @@ -84,6 +85,15 @@ public: mLifecycleManager.addLayers(std::move(layers)); } + void createRootLayerWithUid(uint32_t id, gui::Uid uid) { + std::vector<std::unique_ptr<RequestedLayerState>> layers; + auto args = createArgs(/*id=*/id, /*canBeRoot=*/true, /*parent=*/UNASSIGNED_LAYER_ID, + /*mirror=*/UNASSIGNED_LAYER_ID); + args.ownerUid = uid.val(); + layers.emplace_back(std::make_unique<RequestedLayerState>(args)); + mLifecycleManager.addLayers(std::move(layers)); + } + void createDisplayMirrorLayer(uint32_t id, ui::LayerStack layerStack) { std::vector<std::unique_ptr<RequestedLayerState>> layers; layers.emplace_back(std::make_unique<RequestedLayerState>( @@ -321,6 +331,19 @@ public: mLifecycleManager.applyTransactions(transactions); } + void setFrameRate(uint32_t id, Layer::FrameRate framerate) { + std::vector<TransactionState> transactions; + transactions.emplace_back(); + transactions.back().states.push_back({}); + + transactions.back().states.front().state.what = layer_state_t::eFrameRateChanged; + transactions.back().states.front().layerId = id; + transactions.back().states.front().state.frameRate = framerate.vote.rate.getValue(); + transactions.back().states.front().state.frameRateCompatibility = 0; + transactions.back().states.front().state.changeFrameRateStrategy = 0; + mLifecycleManager.applyTransactions(transactions); + } + void setFrameRateCategory(uint32_t id, int8_t frameRateCategory) { std::vector<TransactionState> transactions; transactions.emplace_back(); @@ -393,6 +416,14 @@ public: GRALLOC_USAGE_PROTECTED /*usage*/)); } + void setFrontBuffer(uint32_t id) { + static uint64_t sBufferId = 1; + setBuffer(id, + std::make_shared<renderengine::mock::FakeExternalTexture>( + 1U /*width*/, 1U /*height*/, sBufferId++, HAL_PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_PROTECTED | AHARDWAREBUFFER_USAGE_FRONT_BUFFER /*usage*/)); + } + void setBufferCrop(uint32_t id, const Rect& bufferCrop) { std::vector<TransactionState> transactions; transactions.emplace_back(); diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index d9d239d2db..f1bd87ccd1 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -80,13 +80,10 @@ cc_test { "FpsTest.cpp", "FramebufferSurfaceTest.cpp", "FrameRateOverrideMappingsTest.cpp", - "FrameRateSelectionPriorityTest.cpp", - "FrameRateSelectionStrategyTest.cpp", "FrameTimelineTest.cpp", "HWComposerTest.cpp", "JankTrackerTest.cpp", "OneShotTimerTest.cpp", - "LayerHistoryTest.cpp", "LayerHistoryIntegrationTest.cpp", "LayerInfoTest.cpp", "LayerMetadataTest.cpp", @@ -116,7 +113,6 @@ cc_test { "SurfaceFlinger_SetPowerModeInternalTest.cpp", "SurfaceFlinger_SetupNewDisplayDeviceInternalTest.cpp", "SchedulerTest.cpp", - "SetFrameRateTest.cpp", "RefreshRateSelectorTest.cpp", "RefreshRateStatsTest.cpp", "RegionSamplingTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp deleted file mode 100644 index d30d5b8223..0000000000 --- a/services/surfaceflinger/tests/unittests/FrameRateSelectionPriorityTest.cpp +++ /dev/null @@ -1,186 +0,0 @@ -/* - * 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 "LibSurfaceFlingerUnittests" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <gui/LayerMetadata.h> - -#include "Layer.h" -#include "TestableSurfaceFlinger.h" -#include "mock/DisplayHardware/MockComposer.h" - -namespace android { - -using testing::_; -using testing::DoAll; -using testing::Mock; -using testing::Return; -using testing::SetArgPointee; - -using android::Hwc2::IComposer; -using android::Hwc2::IComposerClient; - -/** - * This class covers all the test that are related to refresh rate selection. - */ -class RefreshRateSelectionTest : public testing::Test { -public: - RefreshRateSelectionTest(); - ~RefreshRateSelectionTest() override; - -protected: - static constexpr int DEFAULT_DISPLAY_WIDTH = 1920; - static constexpr int DEFAULT_DISPLAY_HEIGHT = 1024; - static constexpr uint32_t WIDTH = 100; - static constexpr uint32_t HEIGHT = 100; - static constexpr uint32_t LAYER_FLAGS = 0; - static constexpr int32_t PRIORITY_UNSET = -1; - - sp<Layer> createBufferStateLayer(); - sp<Layer> createEffectLayer(); - - void setParent(Layer* child, Layer* parent); - void commitTransaction(Layer* layer); - - TestableSurfaceFlinger mFlinger; - - sp<Client> mClient; - sp<Layer> mParent; - sp<Layer> mChild; - sp<Layer> mGrandChild; -}; - -RefreshRateSelectionTest::RefreshRateSelectionTest() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - - mFlinger.setupMockScheduler(); - mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>()); -} - -RefreshRateSelectionTest::~RefreshRateSelectionTest() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); -} - -sp<Layer> RefreshRateSelectionTest::createBufferStateLayer() { - sp<Client> client; - LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", LAYER_FLAGS, - LayerMetadata()); - return sp<Layer>::make(args); -} - -sp<Layer> RefreshRateSelectionTest::createEffectLayer() { - sp<Client> client; - LayerCreationArgs args(mFlinger.flinger(), client, "color-layer", LAYER_FLAGS, LayerMetadata()); - return sp<Layer>::make(args); -} - -void RefreshRateSelectionTest::setParent(Layer* child, Layer* parent) { - child->setParent(sp<Layer>::fromExisting(parent)); -} - -void RefreshRateSelectionTest::commitTransaction(Layer* layer) { - layer->commitTransaction(); -} - -namespace { - -TEST_F(RefreshRateSelectionTest, testPriorityOnBufferStateLayers) { - mParent = createBufferStateLayer(); - mChild = createBufferStateLayer(); - setParent(mChild.get(), mParent.get()); - mGrandChild = createBufferStateLayer(); - setParent(mGrandChild.get(), mChild.get()); - - ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(PRIORITY_UNSET, mGrandChild->getFrameRateSelectionPriority()); - - // Child has its own priority. - mGrandChild->setFrameRateSelectionPriority(1); - commitTransaction(mGrandChild.get()); - ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority()); - - // Child inherits from his parent. - mChild->setFrameRateSelectionPriority(1); - commitTransaction(mChild.get()); - mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET); - commitTransaction(mGrandChild.get()); - ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority()); - - // Grandchild inherits from his grand parent. - mParent->setFrameRateSelectionPriority(1); - commitTransaction(mParent.get()); - mChild->setFrameRateSelectionPriority(PRIORITY_UNSET); - commitTransaction(mChild.get()); - mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET); - commitTransaction(mGrandChild.get()); - ASSERT_EQ(1, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority()); -} - -TEST_F(RefreshRateSelectionTest, testPriorityOnEffectLayers) { - mParent = createEffectLayer(); - mChild = createEffectLayer(); - setParent(mChild.get(), mParent.get()); - mGrandChild = createEffectLayer(); - setParent(mGrandChild.get(), mChild.get()); - - ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(PRIORITY_UNSET, mGrandChild->getFrameRateSelectionPriority()); - - // Child has its own priority. - mGrandChild->setFrameRateSelectionPriority(1); - commitTransaction(mGrandChild.get()); - ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(PRIORITY_UNSET, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority()); - - // Child inherits from his parent. - mChild->setFrameRateSelectionPriority(1); - commitTransaction(mChild.get()); - mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET); - commitTransaction(mGrandChild.get()); - ASSERT_EQ(PRIORITY_UNSET, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority()); - - // Grandchild inherits from his grand parent. - mParent->setFrameRateSelectionPriority(1); - commitTransaction(mParent.get()); - mChild->setFrameRateSelectionPriority(PRIORITY_UNSET); - commitTransaction(mChild.get()); - mGrandChild->setFrameRateSelectionPriority(PRIORITY_UNSET); - commitTransaction(mGrandChild.get()); - ASSERT_EQ(1, mParent->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mChild->getFrameRateSelectionPriority()); - ASSERT_EQ(1, mGrandChild->getFrameRateSelectionPriority()); -} - -} // namespace -} // namespace android diff --git a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp b/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp deleted file mode 100644 index 866eb08913..0000000000 --- a/services/surfaceflinger/tests/unittests/FrameRateSelectionStrategyTest.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright 2023 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 "LibSurfaceFlingerUnittests" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <gui/LayerMetadata.h> - -#include "Layer.h" -#include "LayerTestUtils.h" -#include "TestableSurfaceFlinger.h" -#include "mock/DisplayHardware/MockComposer.h" - -namespace android { - -using testing::_; -using testing::DoAll; -using testing::Mock; -using testing::SetArgPointee; - -using android::Hwc2::IComposer; -using android::Hwc2::IComposerClient; - -using scheduler::LayerHistory; - -using FrameRate = Layer::FrameRate; -using FrameRateCompatibility = Layer::FrameRateCompatibility; -using FrameRateSelectionStrategy = scheduler::LayerInfo::FrameRateSelectionStrategy; - -/** - * This class tests the behaviour of Layer::setFrameRateSelectionStrategy. - */ -class FrameRateSelectionStrategyTest : public BaseLayerTest { -protected: - const FrameRate FRAME_RATE_VOTE1 = FrameRate(11_Hz, FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_VOTE2 = FrameRate(22_Hz, FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_VOTE3 = FrameRate(33_Hz, FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_DEFAULT = FrameRate(Fps(), FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_TREE = FrameRate(Fps(), FrameRateCompatibility::NoVote); - - FrameRateSelectionStrategyTest(); - - void addChild(sp<Layer> layer, sp<Layer> child); - void removeChild(sp<Layer> layer, sp<Layer> child); - void commitTransaction(); - - std::vector<sp<Layer>> mLayers; -}; - -FrameRateSelectionStrategyTest::FrameRateSelectionStrategyTest() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - - mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>()); -} - -void FrameRateSelectionStrategyTest::addChild(sp<Layer> layer, sp<Layer> child) { - layer->addChild(child); -} - -void FrameRateSelectionStrategyTest::removeChild(sp<Layer> layer, sp<Layer> child) { - layer->removeChild(child); -} - -void FrameRateSelectionStrategyTest::commitTransaction() { - for (auto layer : mLayers) { - layer->commitTransaction(); - } -} - -namespace { - -INSTANTIATE_TEST_SUITE_P(PerLayerType, FrameRateSelectionStrategyTest, - testing::Values(std::make_shared<BufferStateLayerFactory>(), - std::make_shared<EffectLayerFactory>()), - PrintToStringParamName); - -TEST_P(FrameRateSelectionStrategyTest, SetAndGet) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - auto layer = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - layer->setFrameRate(FRAME_RATE_VOTE1.vote); - layer->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, layer->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - layer->getDrawingState().frameRateSelectionStrategy); -} - -TEST_P(FrameRateSelectionStrategyTest, SetChildOverrideChildren) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - addChild(parent, child1); - addChild(child1, child2); - - child2->setFrameRate(FRAME_RATE_VOTE1.vote); - child2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - parent->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - child1->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - child2->getDrawingState().frameRateSelectionStrategy); -} - -TEST_P(FrameRateSelectionStrategyTest, SetParentOverrideChildren) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - auto layer1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto layer2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto layer3 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - addChild(layer1, layer2); - addChild(layer2, layer3); - - layer1->setFrameRate(FRAME_RATE_VOTE1.vote); - layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); - layer2->setFrameRate(FRAME_RATE_VOTE2.vote); - layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); - layer3->setFrameRate(FRAME_RATE_VOTE3.vote); - commitTransaction(); - - EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - layer1->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE1, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - layer2->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer3->getDrawingState().frameRateSelectionStrategy); - - layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::Propagate); - commitTransaction(); - - EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer1->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - layer2->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE2, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer3->getDrawingState().frameRateSelectionStrategy); -} - -TEST_P(FrameRateSelectionStrategyTest, OverrideChildrenAndSelf) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - auto layer1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto layer2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto layer3 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - addChild(layer1, layer2); - addChild(layer2, layer3); - - layer1->setFrameRate(FRAME_RATE_VOTE1.vote); - layer2->setFrameRate(FRAME_RATE_VOTE2.vote); - layer2->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::Self); - commitTransaction(); - - EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer1->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, - layer2->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_DEFAULT, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer3->getDrawingState().frameRateSelectionStrategy); - - layer1->setFrameRateSelectionStrategy(FrameRateSelectionStrategy::OverrideChildren); - commitTransaction(); - - EXPECT_EQ(FRAME_RATE_VOTE1, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - layer1->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE1, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, - layer2->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE1, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer3->getDrawingState().frameRateSelectionStrategy); - - layer1->setFrameRate(FRAME_RATE_DEFAULT.vote); - commitTransaction(); - - EXPECT_EQ(FRAME_RATE_TREE, layer1->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::OverrideChildren, - layer1->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE2, layer2->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Self, - layer2->getDrawingState().frameRateSelectionStrategy); - EXPECT_EQ(FRAME_RATE_VOTE2, layer3->getFrameRateForLayerTree()); - EXPECT_EQ(FrameRateSelectionStrategy::Propagate, - layer3->getDrawingState().frameRateSelectionStrategy); -} - -} // namespace -} // namespace android
\ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp index a61fa1edb8..52bb07aca3 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryIntegrationTest.cpp @@ -38,6 +38,7 @@ namespace android::scheduler { using android::mock::createDisplayMode; +using android::mock::createVrrDisplayMode; using namespace com::android::graphics::surfaceflinger; class LayerHistoryIntegrationTest : public surfaceflinger::frontend::LayerSnapshotTestBase { @@ -53,6 +54,8 @@ protected: static constexpr Fps HI_FPS = 90_Hz; static constexpr auto HI_FPS_PERIOD = HI_FPS.getPeriodNsecs(); + static constexpr auto kVrrModeId = DisplayModeId(2); + LayerHistoryIntegrationTest() : LayerSnapshotTestBase() { mFlinger.resetScheduler(mScheduler); mLifecycleManager = {}; @@ -71,6 +74,13 @@ protected: updateLayerSnapshotsAndLayerHistory(time); } + void setFrontBufferWithPresentTime(sp<Layer>& layer, nsecs_t time) { + uint32_t sequence = static_cast<uint32_t>(layer->sequence); + setFrontBuffer(sequence); + layer->setDesiredPresentTime(time, false /*autotimestamp*/); + updateLayerSnapshotsAndLayerHistory(time); + } + LayerHistory& history() { return mScheduler->mutableLayerHistory(); } const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } @@ -135,6 +145,21 @@ protected: return layer; } + auto createLegacyAndFrontedEndLayerWithUid(uint32_t sequence, gui::Uid uid) { + std::string layerName = "test layer:" + std::to_string(sequence); + auto args = LayerCreationArgs{mFlinger.flinger(), + nullptr, + layerName, + 0, + {}, + std::make_optional<uint32_t>(sequence)}; + args.ownerUid = uid.val(); + const auto layer = sp<Layer>::make(args); + mFlinger.injectLegacyLayer(layer); + createRootLayerWithUid(sequence, uid); + return layer; + } + auto destroyLayer(sp<Layer>& layer) { uint32_t sequence = static_cast<uint32_t>(layer->sequence); mFlinger.releaseLegacyLayer(sequence); @@ -157,12 +182,13 @@ protected: ASSERT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate); } - std::shared_ptr<RefreshRateSelector> mSelector = - std::make_shared<RefreshRateSelector>(makeModes(createDisplayMode(DisplayModeId(0), - LO_FPS), - createDisplayMode(DisplayModeId(1), - HI_FPS)), - DisplayModeId(0)); + std::shared_ptr<RefreshRateSelector> mSelector = std::make_shared<RefreshRateSelector>( + makeModes(createDisplayMode(DisplayModeId(0), LO_FPS), + createDisplayMode(DisplayModeId(1), HI_FPS), + createVrrDisplayMode(kVrrModeId, HI_FPS, + hal::VrrConfig{.minFrameIntervalNs = + HI_FPS.getPeriodNsecs()})), + DisplayModeId(0)); mock::SchedulerCallback mSchedulerCallback; TestableSurfaceFlinger mFlinger; @@ -214,6 +240,146 @@ TEST_F(LayerHistoryIntegrationTest, singleLayerMinVoteDefaultCompatibility) { EXPECT_EQ(1u, activeLayerCount()); } +TEST_F(LayerHistoryIntegrationTest, oneLayer) { + createLegacyAndFrontedEndLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + // No layers returned if no layers are active. + EXPECT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); + + // Max returned if active layers have insufficient history. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + setBuffer(1); + updateLayerSnapshotsAndLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + time += LO_FPS_PERIOD; + } + + // Max is returned since we have enough history but there is no timestamp votes. + for (size_t i = 0; i < 10; i++) { + setBuffer(1); + updateLayerSnapshotsAndLayerHistory(time); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + time += LO_FPS_PERIOD; + } +} + +TEST_F(LayerHistoryIntegrationTest, gameFrameRateOverrideMapping) { + SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true); + + history().updateGameDefaultFrameRateOverride(FrameRateOverride({0, 60.0f})); + + auto overridePair = history().getGameFrameRateOverride(0); + EXPECT_EQ(0_Hz, overridePair.first); + EXPECT_EQ(60_Hz, overridePair.second); + + history().updateGameModeFrameRateOverride(FrameRateOverride({0, 40.0f})); + history().updateGameModeFrameRateOverride(FrameRateOverride({1, 120.0f})); + + overridePair = history().getGameFrameRateOverride(0); + EXPECT_EQ(40_Hz, overridePair.first); + EXPECT_EQ(60_Hz, overridePair.second); + + overridePair = history().getGameFrameRateOverride(1); + EXPECT_EQ(120_Hz, overridePair.first); + EXPECT_EQ(0_Hz, overridePair.second); + + history().updateGameDefaultFrameRateOverride(FrameRateOverride({0, 0.0f})); + history().updateGameModeFrameRateOverride(FrameRateOverride({1, 0.0f})); + + overridePair = history().getGameFrameRateOverride(0); + EXPECT_EQ(40_Hz, overridePair.first); + EXPECT_EQ(0_Hz, overridePair.second); + + overridePair = history().getGameFrameRateOverride(1); + EXPECT_EQ(0_Hz, overridePair.first); + EXPECT_EQ(0_Hz, overridePair.second); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerGameFrameRateOverride) { + SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true); + + const uid_t uid = 0; + const Fps gameDefaultFrameRate = Fps::fromValue(30.0f); + const Fps gameModeFrameRate = Fps::fromValue(60.0f); + + auto layer = createLegacyAndFrontedEndLayerWithUid(1, gui::Uid(uid)); + showLayer(1); + + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + // update game default frame rate override + history().updateGameDefaultFrameRateOverride( + FrameRateOverride({uid, gameDefaultFrameRate.getValue()})); + + LayerHistory::Summary summary; + scheduler::LayerProps layerProps = { + .visible = true, + .bounds = {0, 0, 100, 100}, + .transform = {}, + .setFrameRateVote = {}, + .frameRateSelectionPriority = Layer::PRIORITY_UNSET, + .isSmallDirty = false, + .isFrontBuffered = false, + }; + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += gameDefaultFrameRate.getPeriodNsecs(); + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); + ASSERT_EQ(30.0_Hz, summary[0].desiredRefreshRate); + + // test against setFrameRate vote + setFrameRate(1, + Layer::FrameRate(Fps::fromValue(120.0f), Layer::FrameRateCompatibility::Default)); + updateLayerSnapshotsAndLayerHistory(time); + + const Fps setFrameRate = Fps::fromValue(120.0f); + layerProps.setFrameRateVote = + Layer::FrameRate(setFrameRate, Layer::FrameRateCompatibility::Default); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += setFrameRate.getPeriodNsecs(); + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); + ASSERT_EQ(120.0_Hz, summary[0].desiredRefreshRate); + + // update game mode frame rate override + history().updateGameModeFrameRateOverride( + FrameRateOverride({uid, gameModeFrameRate.getValue()})); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += gameModeFrameRate.getPeriodNsecs(); + summary = summarizeLayerHistory(time); + } + + ASSERT_EQ(1u, summary.size()); + ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); + ASSERT_EQ(60.0_Hz, summary[0].desiredRefreshRate); +} + TEST_F(LayerHistoryIntegrationTest, oneInvisibleLayer) { createLegacyAndFrontedEndLayer(1); nsecs_t time = systemTime(); @@ -238,6 +404,110 @@ TEST_F(LayerHistoryIntegrationTest, oneInvisibleLayer) { EXPECT_EQ(0u, activeLayerCount()); } +TEST_F(LayerHistoryIntegrationTest, explicitTimestamp) { + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(LO_FPS, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerNoVote) { + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::NoVote); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + ASSERT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerMinVote) { + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Min); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerMaxVote) { + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Max); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(summarizeLayerHistory(time).empty()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVote) { createLegacyAndFrontedEndLayer(1); setFrameRate(1, 73.4f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, @@ -273,6 +543,335 @@ TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitExactVote) { EXPECT_EQ(1, frequentLayerCount(time)); } +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitExactVote2) { + auto layer = createLegacyAndFrontedEndLayer(1); + setFrameRate(1, 73.4f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + updateLayerSnapshotsAndLayerHistory(time); + + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became infrequent, but the vote stays + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitGte_vrr) { + // Set the test to be on a vrr mode. + SET_FLAG_FOR_TEST(flags::vrr_config, true); + mSelector->setActiveMode(kVrrModeId, HI_FPS); + + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (33_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_GTE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRateCategory(1, 0); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitGte, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(33_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); + + // layer became inactive, but the vote stays + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitGte, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(33_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); +} + +// Test for MRR device with VRR features enabled. +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitGte_nonVrr) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + // The vrr_config flag is explicitly not set false because this test for an MRR device + // should still work in a VRR-capable world. + + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (33_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_GTE, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRateCategory(1, 0); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); + + // layer became infrequent, but the vote stays + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVoteWithCategory_vrrFeatureOff) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false); + + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (73.4_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH); + + // Set default to Min so it is obvious that the vote reset triggered. + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Min); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + // There is only 1 LayerRequirement due to the disabled flag frame_rate_category_mrr. + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); +} + +// This test case should be the same as oneLayerNoVote except instead of layer vote is NoVote, +// the category is NoPreference. +TEST_F(LayerHistoryIntegrationTest, oneLayerCategoryNoPreference) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (0_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_NO_PREFERENCE); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + EXPECT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became infrequent + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + EXPECT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVoteWithCategory) { + SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); + + auto layer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (73.4_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + // There are 2 LayerRequirement's due to the frame rate category. + ASSERT_EQ(2u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + // First LayerRequirement is the layer's category specification + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); + + // Second LayerRequirement is the frame rate specification + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[1].vote); + EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[1].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[1].frameRateCategory); + + // layer became infrequent, but the vote stays + setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(2u, summarizeLayerHistory(time).size()); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); +} + +TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) { + SET_FLAG_FOR_TEST(flags::misc1, true); + + auto layer = createLegacyAndFrontedEndLayer(1); + hideLayer(1); + setFrameRate(1, (12.34_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, + ANATIVEWINDOW_CHANGE_FRAME_RATE_ONLY_IF_SEAMLESS); + setFrameRateCategory(1, ANATIVEWINDOW_FRAME_RATE_CATEGORY_HIGH); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + + nsecs_t time = systemTime(); + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setBufferWithPresentTime(layer, time); + time += HI_FPS_PERIOD; + } + + // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have + // votes to consider for refresh rate selection. + ASSERT_EQ(0u, summarizeLayerHistory(time).size()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayer) { + SET_FLAG_FOR_TEST(flags::misc1, false); + + auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (60_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, 0); + + auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); + hideLayer(2); + setFrameRate(2, (90_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, 0); + + nsecs_t time = systemTime(); + + // Post a buffer to the layers to make them active + setBuffer(1); + setBuffer(2); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(2u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(2u, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, invisibleExplicitLayerDoesNotVote) { + SET_FLAG_FOR_TEST(flags::misc1, true); + + auto explicitVisiblelayer = createLegacyAndFrontedEndLayer(1); + showLayer(1); + setFrameRate(1, (60_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, 0); + + auto explicitInvisiblelayer = createLegacyAndFrontedEndLayer(2); + hideLayer(2); + setFrameRate(2, (90_Hz).getValue(), ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, 0); + + nsecs_t time = systemTime(); + + // Post a buffer to the layers to make them active + setBuffer(1); + setBuffer(2); + updateLayerSnapshotsAndLayerHistory(time); + + EXPECT_EQ(2u, layerCount()); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, + summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryIntegrationTest, frontBufferedLayerVotesMax) { + SET_FLAG_FOR_TEST(flags::vrr_config, true); + + auto layer = createLegacyAndFrontedEndLayer(1); + setFrontBuffer(1); + showLayer(1); + + nsecs_t time = systemTime(); + + EXPECT_EQ(1u, layerCount()); + EXPECT_EQ(0u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // layer is active but infrequent. + for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + setFrontBufferWithPresentTime(layer, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + } + + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); + + // Layer still active due to front buffering, but it's infrequent. + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_EQ(1u, summarizeLayerHistory(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); + EXPECT_EQ(1u, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + EXPECT_EQ(0, animatingLayerCount(time)); +} + TEST_F(LayerHistoryIntegrationTest, oneLayerExplicitCategory) { SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); @@ -805,7 +1404,15 @@ TEST_F(LayerHistoryIntegrationTest, smallDirtyLayer) { // layer is active but infrequent. for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - auto props = layer->getLayerProps(); + scheduler::LayerProps props = { + .visible = false, + .bounds = {0, 0, 100, 100}, + .transform = {}, + .setFrameRateVote = {}, + .frameRateSelectionPriority = Layer::PRIORITY_UNSET, + .isSmallDirty = false, + .isFrontBuffered = false, + }; if (i % 3 == 0) { props.isSmallDirty = false; } else { @@ -838,8 +1445,15 @@ TEST_F(LayerHistoryIntegrationTest, DISABLED_smallDirtyInMultiLayer) { // uiLayer is updating small dirty. for (size_t i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) { - auto props = uiLayer->getLayerProps(); - props.isSmallDirty = true; + scheduler::LayerProps props = { + .visible = false, + .bounds = {0, 0, 100, 100}, + .transform = {}, + .setFrameRateVote = {}, + .frameRateSelectionPriority = Layer::PRIORITY_UNSET, + .isSmallDirty = true, + .isFrontBuffered = false, + }; setBuffer(1); uiLayer->setDesiredPresentTime(0, false /*autotimestamp*/); updateLayerSnapshotsAndLayerHistory(time); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp deleted file mode 100644 index 088d0d233c..0000000000 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ /dev/null @@ -1,1573 +0,0 @@ -/* - * 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. - */ - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wextra" - -#undef LOG_TAG -#define LOG_TAG "LayerHistoryTest" - -#include <Layer.h> -#include <com_android_graphics_surfaceflinger_flags.h> -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <log/log.h> - -#include <common/test/FlagUtils.h> -#include "FpsOps.h" -#include "Scheduler/LayerHistory.h" -#include "Scheduler/LayerInfo.h" -#include "TestableScheduler.h" -#include "TestableSurfaceFlinger.h" -#include "mock/DisplayHardware/MockDisplayMode.h" -#include "mock/MockLayer.h" -#include "mock/MockSchedulerCallback.h" - -using testing::_; -using testing::Return; -using testing::ReturnRef; - -namespace android::scheduler { - -using MockLayer = android::mock::MockLayer; - -using android::mock::createDisplayMode; -using android::mock::createVrrDisplayMode; - -// WARNING: LEGACY TESTS FOR LEGACY FRONT END -// Update LayerHistoryIntegrationTest instead -class LayerHistoryTest : public testing::Test { -protected: - static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::HISTORY_SIZE; - static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfo::kMaxPeriodForFrequentLayerNs; - static constexpr auto FREQUENT_LAYER_WINDOW_SIZE = LayerInfo::kFrequentLayerWindowSize; - static constexpr auto PRESENT_TIME_HISTORY_DURATION = LayerInfo::HISTORY_DURATION; - - static constexpr Fps LO_FPS = 30_Hz; - static constexpr auto LO_FPS_PERIOD = LO_FPS.getPeriodNsecs(); - - static constexpr Fps HI_FPS = 90_Hz; - static constexpr auto HI_FPS_PERIOD = HI_FPS.getPeriodNsecs(); - - LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } - - LayerHistory& history() { return mScheduler->mutableLayerHistory(); } - const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } - - LayerHistory::Summary summarizeLayerHistory(nsecs_t now) { - // LayerHistory::summarize makes no guarantee of the order of the elements in the summary - // however, for testing only, a stable order is required, therefore we sort the list here. - // Any tests requiring ordered results must create layers with names. - auto summary = history().summarize(*mScheduler->refreshRateSelector(), now); - std::sort(summary.begin(), summary.end(), - [](const RefreshRateSelector::LayerRequirement& lhs, - const RefreshRateSelector::LayerRequirement& rhs) -> bool { - return lhs.name < rhs.name; - }); - return summary; - } - - size_t layerCount() const { return mScheduler->layerHistorySize(); } - size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { - return history().mActiveLayerInfos.size(); - } - - auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { - const auto& infos = history().mActiveLayerInfos; - return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) { - return pair.second.second->isFrequent(now).isFrequent; - }); - } - - auto animatingLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { - const auto& infos = history().mActiveLayerInfos; - return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) { - return pair.second.second->isAnimating(now); - }); - } - - auto clearLayerHistoryCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { - const auto& infos = history().mActiveLayerInfos; - return std::count_if(infos.begin(), infos.end(), [now](const auto& pair) { - return pair.second.second->isFrequent(now).clearHistory; - }); - } - - void setDefaultLayerVote(Layer* layer, - LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS { - auto [found, layerPair] = history().findLayer(layer->getSequence()); - if (found != LayerHistory::LayerStatus::NotFound) { - layerPair->second->setDefaultLayerVote(vote); - } - } - - auto createLayer() { return sp<MockLayer>::make(mFlinger.flinger()); } - auto createLayer(std::string name) { - return sp<MockLayer>::make(mFlinger.flinger(), std::move(name)); - } - auto createLayer(std::string name, uint32_t uid) { - return sp<MockLayer>::make(mFlinger.flinger(), std::move(name), std::move(uid)); - } - - void recordFramesAndExpect(const sp<MockLayer>& layer, nsecs_t& time, Fps frameRate, - Fps desiredRefreshRate, int numFrames) { - LayerHistory::Summary summary; - for (int i = 0; i < numFrames; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += frameRate.getPeriodNsecs(); - - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - ASSERT_EQ(desiredRefreshRate, summary[0].desiredRefreshRate); - } - - static constexpr auto kVrrModeId = DisplayModeId(2); - std::shared_ptr<RefreshRateSelector> mSelector = std::make_shared<RefreshRateSelector>( - makeModes(createDisplayMode(DisplayModeId(0), LO_FPS), - createDisplayMode(DisplayModeId(1), HI_FPS), - createVrrDisplayMode(kVrrModeId, HI_FPS, - hal::VrrConfig{.minFrameIntervalNs = - HI_FPS.getPeriodNsecs()})), - DisplayModeId(0)); - - mock::SchedulerCallback mSchedulerCallback; - TestableSurfaceFlinger mFlinger; - TestableScheduler* mScheduler = new TestableScheduler(mSelector, mFlinger, mSchedulerCallback); -}; - -namespace { - -using namespace com::android::graphics::surfaceflinger; - -TEST_F(LayerHistoryTest, singleLayerNoVoteDefaultCompatibility) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - EXPECT_CALL(*layer, getDefaultFrameRateCompatibility()) - .WillOnce(Return(FrameRateCompatibility::NoVote)); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - nsecs_t time = systemTime(); - - // No layers returned if no layers are active. - EXPECT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(0, activeLayerCount()); - - history().record(layer->getSequence(), layer->getLayerProps(), 0, time, - LayerHistory::LayerUpdateType::Buffer); - history().setDefaultFrameRateCompatibility(layer->getSequence(), - - layer->getDefaultFrameRateCompatibility(), - true /* contentDetectionEnabled */); - - EXPECT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(1, activeLayerCount()); -} - -TEST_F(LayerHistoryTest, singleLayerMinVoteDefaultCompatibility) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - EXPECT_CALL(*layer, getDefaultFrameRateCompatibility()) - .WillOnce(Return(FrameRateCompatibility::Min)); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - nsecs_t time = systemTime(); - - EXPECT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(0, activeLayerCount()); - - history().record(layer->getSequence(), layer->getLayerProps(), 0, time, - LayerHistory::LayerUpdateType::Buffer); - history().setDefaultFrameRateCompatibility(layer->getSequence(), - layer->getDefaultFrameRateCompatibility(), - true /* contentDetectionEnabled */); - - auto summary = summarizeLayerHistory(time); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); -} - -TEST_F(LayerHistoryTest, oneLayer) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - // history().registerLayer(layer, LayerHistory::LayerVoteType::Max); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - nsecs_t time = systemTime(); - - // No layers returned if no layers are active. - EXPECT_TRUE(summarizeLayerHistory(time).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->getSequence(), layer->getLayerProps(), 0, time, - LayerHistory::LayerUpdateType::Buffer); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - time += LO_FPS_PERIOD; - } - - // Max is returned since we have enough history but there is no timestamp votes. - for (int i = 0; i < 10; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), 0, time, - LayerHistory::LayerUpdateType::Buffer); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - time += LO_FPS_PERIOD; - } -} - -TEST_F(LayerHistoryTest, gameFrameRateOverrideMapping) { - SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true); - - history().updateGameDefaultFrameRateOverride(FrameRateOverride({0, 60.0f})); - - auto overridePair = history().getGameFrameRateOverride(0); - EXPECT_EQ(0_Hz, overridePair.first); - EXPECT_EQ(60_Hz, overridePair.second); - - history().updateGameModeFrameRateOverride(FrameRateOverride({0, 40.0f})); - history().updateGameModeFrameRateOverride(FrameRateOverride({1, 120.0f})); - - overridePair = history().getGameFrameRateOverride(0); - EXPECT_EQ(40_Hz, overridePair.first); - EXPECT_EQ(60_Hz, overridePair.second); - - overridePair = history().getGameFrameRateOverride(1); - EXPECT_EQ(120_Hz, overridePair.first); - EXPECT_EQ(0_Hz, overridePair.second); - - history().updateGameDefaultFrameRateOverride(FrameRateOverride({0, 0.0f})); - history().updateGameModeFrameRateOverride(FrameRateOverride({1, 0.0f})); - - overridePair = history().getGameFrameRateOverride(0); - EXPECT_EQ(40_Hz, overridePair.first); - EXPECT_EQ(0_Hz, overridePair.second); - - overridePair = history().getGameFrameRateOverride(1); - EXPECT_EQ(0_Hz, overridePair.first); - EXPECT_EQ(0_Hz, overridePair.second); -} - -TEST_F(LayerHistoryTest, oneLayerGameFrameRateOverride) { - SET_FLAG_FOR_TEST(flags::game_default_frame_rate, true); - - const uid_t uid = 0; - const Fps gameDefaultFrameRate = Fps::fromValue(30.0f); - const Fps gameModeFrameRate = Fps::fromValue(60.0f); - const auto layer = createLayer("GameFrameRateLayer", uid); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - EXPECT_CALL(*layer, getOwnerUid()).WillRepeatedly(Return(uid)); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - // update game default frame rate override - history().updateGameDefaultFrameRateOverride( - FrameRateOverride({uid, gameDefaultFrameRate.getValue()})); - - nsecs_t time = systemTime(); - LayerHistory::Summary summary; - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += gameDefaultFrameRate.getPeriodNsecs(); - - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); - ASSERT_EQ(30.0_Hz, summary[0].desiredRefreshRate); - - // test against setFrameRate vote - const Fps setFrameRate = Fps::fromValue(120.0f); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(setFrameRate, Layer::FrameRateCompatibility::Default))); - - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += setFrameRate.getPeriodNsecs(); - - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); - ASSERT_EQ(120.0_Hz, summary[0].desiredRefreshRate); - - // update game mode frame rate override - history().updateGameModeFrameRateOverride( - FrameRateOverride({uid, gameModeFrameRate.getValue()})); - - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += gameModeFrameRate.getPeriodNsecs(); - - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); - ASSERT_EQ(60.0_Hz, summary[0].desiredRefreshRate); -} - -TEST_F(LayerHistoryTest, oneInvisibleLayer) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - nsecs_t time = systemTime(); - - history().record(layer->getSequence(), layer->getLayerProps(), 0, time, - LayerHistory::LayerUpdateType::Buffer); - auto summary = summarizeLayerHistory(time); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - // Layer is still considered inactive so we expect to get Min - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - history().record(layer->getSequence(), layer->getLayerProps(), 0, time, - LayerHistory::LayerUpdateType::Buffer); - - summary = summarizeLayerHistory(time); - EXPECT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(0, activeLayerCount()); -} - -TEST_F(LayerHistoryTest, explicitTimestamp) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += LO_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(LO_FPS, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerNoVote) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::NoVote); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer became inactive - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerMinVote) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Min); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer became inactive - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerMaxVote) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Max); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += LO_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer became inactive - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_TRUE(summarizeLayerHistory(time).empty()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitVote) { - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(73.4_Hz, Layer::FrameRateCompatibility::Default))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer became infrequent, but the vote stays - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitExactVote) { - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly(Return( - Layer::FrameRate(73.4_Hz, 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, - summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer became infrequent, but the vote stays - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, - summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitGte_vrr) { - // Set the test to be on a vrr mode. - SET_FLAG_FOR_TEST(flags::vrr_config, true); - mSelector->setActiveMode(kVrrModeId, HI_FPS); - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly(Return(Layer::FrameRate(33_Hz, Layer::FrameRateCompatibility::Gte, - Seamlessness::OnlySeamless, - FrameRateCategory::Default))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitGte, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(33_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); - - // layer became inactive, but the vote stays - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitGte, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(33_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); -} - -// Test for MRR device with VRR features enabled. -TEST_F(LayerHistoryTest, oneLayerExplicitGte_nonVrr) { - SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); - // The vrr_config flag is explicitly not set false because this test for an MRR device - // should still work in a VRR-capable world. - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly(Return(Layer::FrameRate(33_Hz, Layer::FrameRateCompatibility::Gte, - Seamlessness::OnlySeamless, - FrameRateCategory::Default))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); - - // layer became infrequent, but the vote stays - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory_vrrFeatureOff) { - SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, false); - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(73.4_Hz, Layer::FrameRateCompatibility::Default, - Seamlessness::OnlySeamless, FrameRateCategory::High))); - - // Set default to Min so it is obvious that the vote reset triggered. - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Min); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - // There is only 1 LayerRequirement due to the disabled flag frame_rate_category_mrr. - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[0].frameRateCategory); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitCategory) { - SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(0_Hz, Layer::FrameRateCompatibility::Default, - Seamlessness::OnlySeamless, FrameRateCategory::High))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - // First LayerRequirement is the frame rate specification - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); - - // layer became infrequent, but the vote stays - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); -} - -// This test case should be the same as oneLayerNoVote except instead of layer vote is NoVote, -// the category is NoPreference. -TEST_F(LayerHistoryTest, oneLayerCategoryNoPreference) { - SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly(Return(Layer::FrameRate(0_Hz, Layer::FrameRateCompatibility::Default, - Seamlessness::OnlySeamless, - FrameRateCategory::NoPreference))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - EXPECT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer became infrequent - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - EXPECT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategory) { - SET_FLAG_FOR_TEST(flags::frame_rate_category_mrr, true); - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(73.4_Hz, Layer::FrameRateCompatibility::Default, - Seamlessness::OnlySeamless, FrameRateCategory::High))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - // There are 2 LayerRequirement's due to the frame rate category. - ASSERT_EQ(2, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - // First LayerRequirement is the layer's category specification - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); - - // Second LayerRequirement is the frame rate specification - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summarizeLayerHistory(time)[1].vote); - EXPECT_EQ(73.4_Hz, summarizeLayerHistory(time)[1].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::Default, summarizeLayerHistory(time)[1].frameRateCategory); - - // layer became infrequent, but the vote stays - setDefaultLayerVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(2, summarizeLayerHistory(time).size()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitCategory, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(0_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(FrameRateCategory::High, summarizeLayerHistory(time)[0].frameRateCategory); -} - -TEST_F(LayerHistoryTest, oneLayerExplicitVoteWithCategoryNotVisibleDoesNotVote) { - SET_FLAG_FOR_TEST(flags::misc1, true); - - auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(12.34_Hz, Layer::FrameRateCompatibility::Default, - Seamlessness::OnlySeamless, FrameRateCategory::High))); - - 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->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - } - - // Layer is not visible, so the layer is moved to inactive, infrequent, and it will not have - // votes to consider for refresh rate selection. - ASSERT_EQ(0, summarizeLayerHistory(time).size()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, multipleLayers) { - auto layer1 = createLayer("A"); - auto layer2 = createLayer("B"); - auto layer3 = createLayer("C"); - - EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer1, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer2, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer3, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - EXPECT_EQ(3, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - - LayerHistory::Summary summary; - - // layer1 is active but infrequent. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer1->getSequence(), layer1->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[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->getSequence(), layer2->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - // layer1 is still active but infrequent. - history().record(layer1->getSequence(), layer1->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - - ASSERT_EQ(2, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summary[0].vote); - ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_EQ(HI_FPS, summarizeLayerHistory(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 < 2 * PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2->getSequence(), layer2->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += LO_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(LO_FPS, summary[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->getSequence(), layer2->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - } - - history().record(layer3->getSequence(), layer3->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(2, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summary[1].vote); - EXPECT_EQ(2, activeLayerCount()); - EXPECT_EQ(2, frequentLayerCount(time)); - - // layer3 becomes recently active. - history().record(layer3->getSequence(), layer3->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - summary = summarizeLayerHistory(time); - ASSERT_EQ(2, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_EQ(HI_FPS, summary[1].desiredRefreshRate); - EXPECT_EQ(2, activeLayerCount()); - EXPECT_EQ(2, frequentLayerCount(time)); - - // layer1 expires. - layer1.clear(); - summary = summarizeLayerHistory(time); - ASSERT_EQ(2, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[1].vote); - EXPECT_EQ(HI_FPS, summary[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->getSequence(), layer2->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += LO_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(LO_FPS, summary[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer2 expires. - layer2.clear(); - summary = summarizeLayerHistory(time); - EXPECT_TRUE(summary.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 + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) { - history().record(layer3->getSequence(), layer3->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_EQ(HI_FPS, summary[0].desiredRefreshRate); - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - - // layer3 expires. - layer3.clear(); - summary = summarizeLayerHistory(time); - EXPECT_TRUE(summary.empty()); - EXPECT_EQ(0, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, inactiveLayers) { - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - // the very first updates makes the layer frequent - for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - } - - // the next update with the MAX_FREQUENT_LAYER_PERIOD_NS will get us to infrequent - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - - // advance the time for the previous frame to be inactive - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - - // Now even if we post a quick few frame we should stay infrequent - for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - } - - // More quick frames will get us to frequent again - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, invisibleExplicitLayer) { - SET_FLAG_FOR_TEST(flags::misc1, false); - - auto explicitVisiblelayer = createLayer(); - auto explicitInvisiblelayer = createLayer(); - - EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) - .WillRepeatedly(Return( - Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); - - EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); - EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) - .WillRepeatedly(Return( - Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); - - nsecs_t time = systemTime(); - - // Post a buffer to the layers to make them active - history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(), - time, time, LayerHistory::LayerUpdateType::Buffer); - history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(), - time, time, LayerHistory::LayerUpdateType::Buffer); - - EXPECT_EQ(2, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, - summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(2, activeLayerCount()); - EXPECT_EQ(2, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, invisibleExplicitLayerDoesNotVote) { - SET_FLAG_FOR_TEST(flags::misc1, true); - - auto explicitVisiblelayer = createLayer(); - auto explicitInvisiblelayer = createLayer(); - - EXPECT_CALL(*explicitVisiblelayer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*explicitVisiblelayer, getFrameRateForLayerTree()) - .WillRepeatedly(Return( - Layer::FrameRate(60_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); - - EXPECT_CALL(*explicitInvisiblelayer, isVisible()).WillRepeatedly(Return(false)); - EXPECT_CALL(*explicitInvisiblelayer, getFrameRateForLayerTree()) - .WillRepeatedly(Return( - Layer::FrameRate(90_Hz, Layer::FrameRateCompatibility::ExactOrMultiple))); - - nsecs_t time = systemTime(); - - // Post a buffer to the layers to make them active - history().record(explicitVisiblelayer->getSequence(), explicitVisiblelayer->getLayerProps(), - time, time, LayerHistory::LayerUpdateType::Buffer); - history().record(explicitInvisiblelayer->getSequence(), explicitInvisiblelayer->getLayerProps(), - time, time, LayerHistory::LayerUpdateType::Buffer); - - EXPECT_EQ(2, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, - summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); -} - -TEST_F(LayerHistoryTest, infrequentAnimatingLayer) { - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // layer is active but infrequent. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // another update with the same cadence keep in infrequent - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // an update as animation will immediately vote for Max - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::AnimationTX); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(1, animatingLayerCount(time)); -} - -TEST_F(LayerHistoryTest, frontBufferedLayerVotesMax) { - SET_FLAG_FOR_TEST(flags::vrr_config, true); - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - EXPECT_CALL(*layer, isFrontBuffered()).WillRepeatedly(Return(true)); - - nsecs_t time = systemTime(); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // layer is active but infrequent. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - } - - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // Layer still active due to front buffering, but it's infrequent. - time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); -} - -TEST_F(LayerHistoryTest, frequentLayerBecomingInfrequentAndBack) { - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // Fill up the window with frequent updates - for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += (60_Hz).getPeriodNsecs(); - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - } - - // posting a buffer after long inactivity should retain the layer as active - time += std::chrono::nanoseconds(3s).count(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(0, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(60_Hz, summarizeLayerHistory(time)[0].desiredRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // posting more infrequent buffer should make the layer infrequent - time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(0, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // posting another buffer should keep the layer infrequent - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(0, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // posting more buffers would mean starting of an animation, so making the layer frequent - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(1, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // posting a buffer after long inactivity should retain the layer as active - time += std::chrono::nanoseconds(3s).count(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(0, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // posting another buffer should keep the layer frequent - time += (60_Hz).getPeriodNsecs(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(0, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); -} - -TEST_F(LayerHistoryTest, inconclusiveLayerBecomingFrequent) { - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // Fill up the window with frequent updates - for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += (60_Hz).getPeriodNsecs(); - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - } - - // posting infrequent buffers after long inactivity should make the layer - // inconclusive but frequent. - time += std::chrono::nanoseconds(3s).count(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += (MAX_FREQUENT_LAYER_PERIOD_NS + 1ms).count(); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(0, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // posting more buffers should make the layer frequent and switch the refresh rate to max - // by clearing the history - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - EXPECT_EQ(1, clearLayerHistoryCount(time)); - ASSERT_EQ(1, summarizeLayerHistory(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, summarizeLayerHistory(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); -} - -TEST_F(LayerHistoryTest, getFramerate) { - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - EXPECT_EQ(0, animatingLayerCount(time)); - - // layer is active but infrequent. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer->getSequence(), layer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - } - - float expectedFramerate = 1e9f / MAX_FREQUENT_LAYER_PERIOD_NS.count(); - EXPECT_FLOAT_EQ(expectedFramerate, history().getLayerFramerate(time, layer->getSequence())); -} - -TEST_F(LayerHistoryTest, heuristicLayer60Hz) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - for (float fps = 54.0f; fps < 65.0f; fps += 0.1f) { - recordFramesAndExpect(layer, time, Fps::fromValue(fps), 60_Hz, PRESENT_TIME_HISTORY_SIZE); - } -} - -TEST_F(LayerHistoryTest, heuristicLayer60_30Hz) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - recordFramesAndExpect(layer, time, 60_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); - - recordFramesAndExpect(layer, time, 60_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 30_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 30_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 60_Hz, 60_Hz, PRESENT_TIME_HISTORY_SIZE); -} - -TEST_F(LayerHistoryTest, heuristicLayerNotOscillating) { - SET_FLAG_FOR_TEST(flags::use_known_refresh_rate_for_fps_consistency, false); - - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.9_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.9_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); -} - -TEST_F(LayerHistoryTest, heuristicLayerNotOscillating_useKnownRefreshRate) { - SET_FLAG_FOR_TEST(flags::use_known_refresh_rate_for_fps_consistency, true); - - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.9_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 26.9_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 27.1_Hz, 24_Hz, PRESENT_TIME_HISTORY_SIZE); - recordFramesAndExpect(layer, time, 27.1_Hz, 30_Hz, PRESENT_TIME_HISTORY_SIZE); -} - -TEST_F(LayerHistoryTest, smallDirtyLayer) { - auto layer = createLayer(); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - nsecs_t time = systemTime(); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - - LayerHistory::Summary summary; - - // layer is active but infrequent. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - auto props = layer->getLayerProps(); - if (i % 3 == 0) { - props.isSmallDirty = false; - } else { - props.isSmallDirty = true; - } - - history().record(layer->getSequence(), props, time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - ASSERT_EQ(LayerHistory::LayerVoteType::Heuristic, summary[0].vote); - EXPECT_GE(HI_FPS, summary[0].desiredRefreshRate); -} - -TEST_F(LayerHistoryTest, smallDirtyInMultiLayer) { - auto layer1 = createLayer("UI"); - auto layer2 = createLayer("Video"); - - EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer1, getFrameRateForLayerTree()).WillRepeatedly(Return(Layer::FrameRate())); - - EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer2, getFrameRateForLayerTree()) - .WillRepeatedly( - Return(Layer::FrameRate(30_Hz, Layer::FrameRateCompatibility::Default))); - - nsecs_t time = systemTime(); - - EXPECT_EQ(2, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - - LayerHistory::Summary summary; - - // layer1 is updating small dirty. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE + FREQUENT_LAYER_WINDOW_SIZE + 1; i++) { - auto props = layer1->getLayerProps(); - props.isSmallDirty = true; - history().record(layer1->getSequence(), props, 0 /*presentTime*/, time, - LayerHistory::LayerUpdateType::Buffer); - history().record(layer2->getSequence(), layer2->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - time += HI_FPS_PERIOD; - summary = summarizeLayerHistory(time); - } - - ASSERT_EQ(1, summary.size()); - ASSERT_EQ(LayerHistory::LayerVoteType::ExplicitDefault, summary[0].vote); - ASSERT_EQ(30_Hz, summary[0].desiredRefreshRate); -} - -class LayerHistoryTestParameterized : public LayerHistoryTest, - public testing::WithParamInterface<std::chrono::nanoseconds> { -}; - -TEST_P(LayerHistoryTestParameterized, HeuristicLayerWithInfrequentLayer) { - std::chrono::nanoseconds infrequentUpdateDelta = GetParam(); - auto heuristicLayer = createLayer("HeuristicLayer"); - - EXPECT_CALL(*heuristicLayer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*heuristicLayer, getFrameRateForLayerTree()) - .WillRepeatedly(Return(Layer::FrameRate())); - - auto infrequentLayer = createLayer("InfrequentLayer"); - EXPECT_CALL(*infrequentLayer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*infrequentLayer, getFrameRateForLayerTree()) - .WillRepeatedly(Return(Layer::FrameRate())); - - const nsecs_t startTime = systemTime(); - - const std::chrono::nanoseconds heuristicUpdateDelta = 41'666'667ns; - history().record(heuristicLayer->getSequence(), heuristicLayer->getLayerProps(), startTime, - startTime, LayerHistory::LayerUpdateType::Buffer); - history().record(infrequentLayer->getSequence(), heuristicLayer->getLayerProps(), startTime, - startTime, LayerHistory::LayerUpdateType::Buffer); - - nsecs_t time = startTime; - nsecs_t lastInfrequentUpdate = startTime; - const int totalInfrequentLayerUpdates = FREQUENT_LAYER_WINDOW_SIZE * 5; - int infrequentLayerUpdates = 0; - while (infrequentLayerUpdates <= totalInfrequentLayerUpdates) { - time += heuristicUpdateDelta.count(); - history().record(heuristicLayer->getSequence(), heuristicLayer->getLayerProps(), time, time, - LayerHistory::LayerUpdateType::Buffer); - - if (time - lastInfrequentUpdate >= infrequentUpdateDelta.count()) { - ALOGI("submitting infrequent frame [%d/%d]", infrequentLayerUpdates, - totalInfrequentLayerUpdates); - lastInfrequentUpdate = time; - history().record(infrequentLayer->getSequence(), infrequentLayer->getLayerProps(), time, - time, LayerHistory::LayerUpdateType::Buffer); - infrequentLayerUpdates++; - } - - if (time - startTime > PRESENT_TIME_HISTORY_DURATION.count()) { - ASSERT_NE(0, summarizeLayerHistory(time).size()); - ASSERT_GE(2, summarizeLayerHistory(time).size()); - - bool max = false; - bool min = false; - Fps heuristic; - for (const auto& layer : summarizeLayerHistory(time)) { - if (layer.vote == LayerHistory::LayerVoteType::Heuristic) { - heuristic = layer.desiredRefreshRate; - } else if (layer.vote == LayerHistory::LayerVoteType::Max) { - max = true; - } else if (layer.vote == LayerHistory::LayerVoteType::Min) { - min = true; - } - } - - if (infrequentLayerUpdates > FREQUENT_LAYER_WINDOW_SIZE) { - EXPECT_EQ(24_Hz, heuristic); - EXPECT_FALSE(max); - if (summarizeLayerHistory(time).size() == 2) { - EXPECT_TRUE(min); - } - } - } - } -} - -INSTANTIATE_TEST_CASE_P(LeapYearTests, LayerHistoryTestParameterized, - ::testing::Values(1s, 2s, 3s, 4s, 5s)); - -} // namespace -} // namespace android::scheduler - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wextra" diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 3df724a09e..125a4e4cdc 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -162,7 +162,17 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentIsNoopWhenModeSwitchingIsNotSup // recordLayerHistory should be a noop ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); - mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0, + scheduler::LayerProps layerProps = { + .visible = true, + .bounds = {0, 0, 100, 100}, + .transform = {}, + .setFrameRateVote = {}, + .frameRateSelectionPriority = Layer::PRIORITY_UNSET, + .isSmallDirty = false, + .isFrontBuffered = false, + }; + + mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, 0, LayerHistory::LayerUpdateType::Buffer); ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); @@ -188,7 +198,16 @@ TEST_F(SchedulerTest, updateDisplayModes) { kDisplay1Mode60->getId())); ASSERT_EQ(0u, mScheduler->getNumActiveLayers()); - mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, 0, + scheduler::LayerProps layerProps = { + .visible = true, + .bounds = {0, 0, 100, 100}, + .transform = {}, + .setFrameRateVote = {}, + .frameRateSelectionPriority = Layer::PRIORITY_UNSET, + .isSmallDirty = false, + .isFrontBuffered = false, + }; + mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, 0, LayerHistory::LayerUpdateType::Buffer); ASSERT_EQ(1u, mScheduler->getNumActiveLayers()); } @@ -225,9 +244,16 @@ TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) { kDisplay1Mode60->getId())); const sp<MockLayer> layer = sp<MockLayer>::make(mFlinger.flinger()); - EXPECT_CALL(*layer, isVisible()).WillOnce(Return(true)); - - mScheduler->recordLayerHistory(layer->getSequence(), layer->getLayerProps(), 0, systemTime(), + scheduler::LayerProps layerProps = { + .visible = true, + .bounds = {0, 0, 0, 0}, + .transform = {}, + .setFrameRateVote = {}, + .frameRateSelectionPriority = Layer::PRIORITY_UNSET, + .isSmallDirty = false, + .isFrontBuffered = false, + }; + mScheduler->recordLayerHistory(layer->getSequence(), layerProps, 0, systemTime(), LayerHistory::LayerUpdateType::Buffer); constexpr hal::PowerMode kPowerModeOn = hal::PowerMode::ON; diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp deleted file mode 100644 index 4705dd1cc7..0000000000 --- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp +++ /dev/null @@ -1,390 +0,0 @@ -/* - * 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 "LibSurfaceFlingerUnittests" - -#include <gmock/gmock.h> -#include <gtest/gtest.h> -#include <gui/FrameRateUtils.h> -#include <gui/LayerMetadata.h> - -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wconversion" -#include "Layer.h" -// TODO(b/129481165): remove the #pragma below and fix conversion issues -#pragma clang diagnostic pop // ignored "-Wconversion" -#include "FpsOps.h" -#include "LayerTestUtils.h" -#include "TestableSurfaceFlinger.h" -#include "mock/DisplayHardware/MockComposer.h" -#include "mock/MockVsyncController.h" - -namespace android { -using testing::_; -using testing::DoAll; -using testing::Mock; -using testing::SetArgPointee; - -using android::Hwc2::IComposer; -using android::Hwc2::IComposerClient; - -using scheduler::LayerHistory; - -using FrameRate = Layer::FrameRate; -using FrameRateCompatibility = Layer::FrameRateCompatibility; - -/** - * This class tests the behaviour of Layer::SetFrameRate and Layer::GetFrameRate - */ -class SetFrameRateTest : public BaseLayerTest { -protected: - const FrameRate FRAME_RATE_VOTE1 = FrameRate(67_Hz, FrameRateCompatibility::Default); - const FrameRate FRAME_RATE_VOTE2 = FrameRate(14_Hz, FrameRateCompatibility::ExactOrMultiple); - const FrameRate FRAME_RATE_VOTE3 = FrameRate(99_Hz, FrameRateCompatibility::NoVote); - const FrameRate FRAME_RATE_TREE = FrameRate(Fps(), FrameRateCompatibility::NoVote); - const FrameRate FRAME_RATE_NO_VOTE = FrameRate(Fps(), FrameRateCompatibility::Default); - - SetFrameRateTest(); - - void addChild(sp<Layer> layer, sp<Layer> child); - void removeChild(sp<Layer> layer, sp<Layer> child); - void commitTransaction(); - - std::vector<sp<Layer>> mLayers; -}; - -SetFrameRateTest::SetFrameRateTest() { - const ::testing::TestInfo* const test_info = - ::testing::UnitTest::GetInstance()->current_test_info(); - ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - - mFlinger.setupComposer(std::make_unique<Hwc2::mock::Composer>()); -} - -void SetFrameRateTest::addChild(sp<Layer> layer, sp<Layer> child) { - layer->addChild(child); -} - -void SetFrameRateTest::removeChild(sp<Layer> layer, sp<Layer> child) { - layer->removeChild(child); -} - -void SetFrameRateTest::commitTransaction() { - for (auto layer : mLayers) { - layer->commitTransaction(); - } -} - -namespace { - -TEST_P(SetFrameRateTest, SetAndGet) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto layer = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - layer->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, layer->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetParent) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - - child2->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetParentAllVote) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - - child2->setFrameRate(FRAME_RATE_VOTE1.vote); - child1->setFrameRate(FRAME_RATE_VOTE2.vote); - parent->setFrameRate(FRAME_RATE_VOTE3.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE2, child2->getFrameRateForLayerTree()); - - child1->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE3, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE3, child2->getFrameRateForLayerTree()); - - parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetChild) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - - parent->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetChildAllVote) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - - child2->setFrameRate(FRAME_RATE_VOTE1.vote); - child1->setFrameRate(FRAME_RATE_VOTE2.vote); - parent->setFrameRate(FRAME_RATE_VOTE3.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - child1->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetChildAddAfterVote) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - - parent->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - - addChild(child1, child2); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetChildRemoveAfterVote) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - - parent->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - - removeChild(child1, child2); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - - parent->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -TEST_P(SetFrameRateTest, SetAndGetParentNotInTree) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - auto child2_1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, child2); - addChild(child1, child2_1); - - child2->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2_1->getFrameRateForLayerTree()); - - child2->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2_1->getFrameRateForLayerTree()); -} - -INSTANTIATE_TEST_SUITE_P(PerLayerType, SetFrameRateTest, - testing::Values(std::make_shared<BufferStateLayerFactory>(), - std::make_shared<EffectLayerFactory>()), - PrintToStringParamName); - -TEST_P(SetFrameRateTest, SetOnParentActivatesTree) { - const auto& layerFactory = GetParam(); - - auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - auto child = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - addChild(parent, child); - - parent->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - - auto& history = mFlinger.mutableScheduler().mutableLayerHistory(); - history.record(parent->getSequence(), parent->getLayerProps(), 0, 0, - LayerHistory::LayerUpdateType::Buffer); - history.record(child->getSequence(), child->getLayerProps(), 0, 0, - LayerHistory::LayerUpdateType::Buffer); - - const auto selectorPtr = mFlinger.mutableScheduler().refreshRateSelector(); - const auto summary = history.summarize(*selectorPtr, 0); - - ASSERT_EQ(2u, summary.size()); - EXPECT_EQ(FRAME_RATE_VOTE1.vote.rate, summary[0].desiredRefreshRate); - EXPECT_EQ(FRAME_RATE_VOTE1.vote.rate, summary[1].desiredRefreshRate); -} - -TEST_P(SetFrameRateTest, addChildForParentWithTreeVote) { - EXPECT_CALL(*mFlinger.scheduler(), scheduleFrame(_)).Times(1); - - const auto& layerFactory = GetParam(); - - const auto parent = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - const auto child1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - const auto child2 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - const auto childOfChild1 = mLayers.emplace_back(layerFactory->createLayer(mFlinger)); - - addChild(parent, child1); - addChild(child1, childOfChild1); - - childOfChild1->setFrameRate(FRAME_RATE_VOTE1.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, childOfChild1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - - addChild(parent, child2); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_TREE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_VOTE1, childOfChild1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); - - childOfChild1->setFrameRate(FRAME_RATE_NO_VOTE.vote); - commitTransaction(); - EXPECT_EQ(FRAME_RATE_NO_VOTE, parent->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, childOfChild1->getFrameRateForLayerTree()); - EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree()); -} - -} // namespace -} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index 002fa9fb55..fdb6f4dafe 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -24,16 +24,10 @@ namespace android::mock { class MockLayer : public Layer { public: MockLayer(SurfaceFlinger* flinger, std::string name) - : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) { - EXPECT_CALL(*this, getDefaultFrameRateCompatibility()) - .WillOnce(testing::Return(scheduler::FrameRateCompatibility::Default)); - } + : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {})) {} MockLayer(SurfaceFlinger* flinger, std::string name, std::optional<uint32_t> uid) - : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {}, uid)) { - EXPECT_CALL(*this, getDefaultFrameRateCompatibility()) - .WillOnce(testing::Return(scheduler::FrameRateCompatibility::Default)); - } + : Layer(LayerCreationArgs(flinger, nullptr, std::move(name), 0, {}, uid)) {} explicit MockLayer(SurfaceFlinger* flinger) : MockLayer(flinger, "TestLayer") {} |