diff options
author | 2020-01-16 21:18:46 +0000 | |
---|---|---|
committer | 2020-01-16 21:18:46 +0000 | |
commit | 92bd250eda0de9b0d3d966f285a8a75fcfd85149 (patch) | |
tree | 81b6b59e7beaf1d49a4c31f452fbe937e2c1e8d6 | |
parent | 0dbbf7492c2816376129c8751f7e1ddd7c3bdf7f (diff) | |
parent | c84d09b6464242b1809ffb4f7faa5b2632f4a5e0 (diff) |
Merge "SF Generalization of Refresh Rates: Adding layer priority hint"
-rw-r--r-- | libs/gui/LayerState.cpp | 12 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 16 | ||||
-rw-r--r-- | libs/gui/include/gui/LayerState.h | 7 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 25 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 9 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/LayerHistory.cpp | 20 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/LayerHistory.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 18 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp | 283 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/mock/MockLayer.h | 1 |
13 files changed, 394 insertions, 12 deletions
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index a7c4f4670a..8b448ff3f6 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -110,6 +110,9 @@ status_t layer_state_t::write(Parcel& output) const } } output.writeFloat(shadowRadius); + + output.writeInt32(frameRateSelectionPriority); + return NO_ERROR; } @@ -188,6 +191,9 @@ status_t layer_state_t::read(const Parcel& input) listeners.emplace_back(listener, callbackIds); } shadowRadius = input.readFloat(); + + frameRateSelectionPriority = input.readInt32(); + return NO_ERROR; } @@ -406,12 +412,14 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eMetadataChanged; metadata.merge(other.metadata); } - if (other.what & eShadowRadiusChanged) { what |= eShadowRadiusChanged; shadowRadius = other.shadowRadius; } - + if (other.what & eFrameRateSelectionPriority) { + what |= eFrameRateSelectionPriority; + frameRateSelectionPriority = other.frameRateSelectionPriority; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5e259e258c..2ef33cf253 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1192,6 +1192,22 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setColor } SurfaceComposerClient::Transaction& +SurfaceComposerClient::Transaction::setFrameRateSelectionPriority(const sp<SurfaceControl>& sc, + int32_t priority) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + + s->what |= layer_state_t::eFrameRateSelectionPriority; + s->frameRateSelectionPriority = priority; + + registerSurfaceControlForCallback(sc); + return *this; +} + +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::addTransactionCompletedCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext) { auto listener = TransactionCompletedListener::getInstance(); diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index fb186396a6..03e91c4905 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -99,6 +99,7 @@ struct layer_state_t { eBackgroundColorChanged = 0x4'00000000, eMetadataChanged = 0x8'00000000, eColorSpaceAgnosticChanged = 0x10'00000000, + eFrameRateSelectionPriority = 0x20'00000000, }; layer_state_t() @@ -128,7 +129,8 @@ struct layer_state_t { bgColorAlpha(0), bgColorDataspace(ui::Dataspace::UNKNOWN), colorSpaceAgnostic(false), - shadowRadius(0.0f) { + shadowRadius(0.0f), + frameRateSelectionPriority(-1) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -209,6 +211,9 @@ struct layer_state_t { // Draws a shadow around the surface. float shadowRadius; + + // Priority of the layer assigned by Window Manager. + int32_t frameRateSelectionPriority; }; struct ComposerState { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 44f29eaa6f..6a3f452f77 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -483,6 +483,9 @@ public: Transaction& setDesiredPresentTime(nsecs_t desiredPresentTime); Transaction& setColorSpaceAgnostic(const sp<SurfaceControl>& sc, const bool agnostic); + // Sets information about the priority of the frame. + Transaction& setFrameRateSelectionPriority(const sp<SurfaceControl>& sc, int32_t priority); + Transaction& addTransactionCompletedCallback( TransactionCompletedCallbackTakesContext callback, void* callbackContext); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2593681b6b..5bba7d312b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -108,6 +108,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.api = -1; mCurrentState.hasColorTransform = false; mCurrentState.colorSpaceAgnostic = false; + mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET; mCurrentState.metadata = args.metadata; mCurrentState.shadowRadius = 0.f; @@ -1120,6 +1121,7 @@ bool Layer::setTransparentRegionHint(const Region& transparent) { setTransactionFlags(eTransactionNeeded); return true; } + bool Layer::setFlags(uint8_t flags, uint8_t mask) { const uint32_t newFlags = (mCurrentState.flags & ~mask) | (flags & mask); if (mCurrentState.flags == newFlags) return false; @@ -1176,6 +1178,29 @@ bool Layer::setColorSpaceAgnostic(const bool agnostic) { return true; } +bool Layer::setFrameRateSelectionPriority(int32_t priority) { + if (mCurrentState.frameRateSelectionPriority == priority) return false; + mCurrentState.frameRateSelectionPriority = priority; + mCurrentState.sequence++; + mCurrentState.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; +} + uint32_t Layer::getLayerStack() const { auto p = mDrawingParent.promote(); if (p == nullptr) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 174ac8da1e..b8a35392f8 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -96,6 +96,7 @@ struct LayerCreationArgs { class Layer : public compositionengine::LayerFE { static std::atomic<int32_t> sSequence; + static constexpr int32_t PRIORITY_UNSET = -1; public: mutable bool contentDirty{false}; @@ -220,6 +221,9 @@ public: // Length of the cast shadow. If the radius is > 0, a shadow of length shadowRadius will // be rendered around the layer. float shadowRadius; + + // Priority of the layer assigned by Window Manager. + int32_t frameRateSelectionPriority; }; explicit Layer(const LayerCreationArgs& args); @@ -337,6 +341,10 @@ public: virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); bool setShadowRadius(float shadowRadius); + virtual bool setFrameRateSelectionPriority(int32_t priority); + // 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 ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; } @@ -755,6 +763,7 @@ protected: // For unit tests friend class TestableSurfaceFlinger; + friend class RefreshRateSelectionTest; virtual void commitTransaction(const State& stateToCommit); diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index cf79d9fcf7..aaac1ec677 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -48,6 +48,12 @@ bool traceEnabled() { return atoi(value); } +bool useFrameRatePriority() { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.sf.use_frame_rate_priority", value, "1"); + return atoi(value); +} + void trace(const wp<Layer>& weak, int fps) { const auto layer = weak.promote(); if (!layer) return; @@ -60,7 +66,8 @@ void trace(const wp<Layer>& weak, int fps) { } // namespace -LayerHistory::LayerHistory() : mTraceEnabled(traceEnabled()) {} +LayerHistory::LayerHistory() + : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {} LayerHistory::~LayerHistory() = default; void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate) { @@ -94,16 +101,23 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { partitionLayers(now); // Find the maximum refresh rate among recently active layers. - for (const auto& [layer, info] : activeLayers()) { + for (const auto& [activeLayer, info] : activeLayers()) { const bool recent = info->isRecentlyActive(now); + if (recent || CC_UNLIKELY(mTraceEnabled)) { const float refreshRate = info->getRefreshRate(now); if (recent && refreshRate > maxRefreshRate) { + if (const auto layer = activeLayer.promote(); layer) { + const int32_t priority = layer->getFrameRateSelectionPriority(); + // TODO(b/142507166): This is where the scoring algorithm should live. + // Layers should be organized by priority + ALOGD("Layer has priority: %d", priority); + } maxRefreshRate = refreshRate; } if (CC_UNLIKELY(mTraceEnabled)) { - trace(layer, std::round(refreshRate)); + trace(activeLayer, std::round(refreshRate)); } } } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index d92e5c3136..188fa64011 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -106,6 +106,9 @@ private: // Whether to emit systrace output and debug logs. const bool mTraceEnabled; + + // Whether to use priority sent from WindowManager to determine the relevancy of the layer. + const bool mUseFrameRatePriority; }; } // namespace impl diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b7a2c760e6..e90cf41707 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1747,12 +1747,6 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { mGpuFrameMissedCount++; } - mScheduler->chooseRefreshRateForContent(); - - if (performSetActiveConfig()) { - break; - } - if (frameMissed && mPropagateBackpressure) { if ((hwcFrameMissed && !gpuFrameMissed) || mPropagateBackpressureClientComposition) { @@ -1769,6 +1763,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { bool refreshNeeded = handleMessageTransaction(); refreshNeeded |= handleMessageInvalidate(); + // Layers need to get updated (in the previous line) before we can use them for + // choosing the refresh rate. + mScheduler->chooseRefreshRateForContent(); + if (performSetActiveConfig()) { + break; + } + updateCursorAsync(); updateInputFlinger(); @@ -3474,6 +3475,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( if (what & layer_state_t::eShadowRadiusChanged) { if (layer->setShadowRadius(s.shadowRadius)) flags |= eTraversalNeeded; } + if (what & layer_state_t::eFrameRateSelectionPriority) { + if (privileged && layer->setFrameRateSelectionPriority(s.frameRateSelectionPriority)) { + flags |= eTraversalNeeded; + } + } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in // the same transaction, then we have to make sure we reparent the children first so we do not diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index e4ef19ea7a..becf484243 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -49,6 +49,7 @@ cc_test { "SchedulerTest.cpp", "SchedulerUtilsTest.cpp", "RefreshRateConfigsTest.cpp", + "RefreshRateSelectionTest.cpp", "RefreshRateStatsTest.cpp", "RegionSamplingTest.cpp", "TimeStatsTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index f055fe72ac..b5848381cc 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -64,6 +64,7 @@ namespace { TEST_F(LayerHistoryTest, oneLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -90,6 +91,7 @@ TEST_F(LayerHistoryTest, oneLayer) { TEST_F(LayerHistoryTest, oneHDRLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -109,6 +111,7 @@ TEST_F(LayerHistoryTest, oneHDRLayer) { TEST_F(LayerHistoryTest, explicitTimestamp) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -130,8 +133,13 @@ TEST_F(LayerHistoryTest, multipleLayers) { auto layer3 = createLayer(); EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer1, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer3, getFrameSelectionPriority()).WillRepeatedly(Return(1)); nsecs_t time = mTime; diff --git a/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp new file mode 100644 index 0000000000..c23a6601d0 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/RefreshRateSelectionTest.cpp @@ -0,0 +1,283 @@ +/* + * 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 "BufferQueueLayer.h" +#include "BufferStateLayer.h" +#include "ColorLayer.h" +#include "Layer.h" +#include "TestableSurfaceFlinger.h" +#include "mock/DisplayHardware/MockComposer.h" +#include "mock/MockDispSync.h" +#include "mock/MockEventControlThread.h" +#include "mock/MockEventThread.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; + +using FakeHwcDisplayInjector = TestableSurfaceFlinger::FakeHwcDisplayInjector; + +/** + * 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; + + void setupScheduler(); + void setupComposer(int virtualDisplayCount); + sp<BufferQueueLayer> createBufferQueueLayer(); + sp<BufferStateLayer> createBufferStateLayer(); + sp<ColorLayer> createColorLayer(); + + void setParent(Layer* child, Layer* parent); + void commitTransaction(Layer* layer); + + TestableSurfaceFlinger mFlinger; + Hwc2::mock::Composer* mComposer = nullptr; + + 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()); + + setupScheduler(); + setupComposer(0); +} + +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<BufferQueueLayer> RefreshRateSelectionTest::createBufferQueueLayer() { + sp<Client> client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT, + LAYER_FLAGS, LayerMetadata()); + return new BufferQueueLayer(args); +} + +sp<BufferStateLayer> RefreshRateSelectionTest::createBufferStateLayer() { + sp<Client> client; + LayerCreationArgs args(mFlinger.flinger(), client, "buffer-queue-layer", WIDTH, HEIGHT, + LAYER_FLAGS, LayerMetadata()); + return new BufferStateLayer(args); +} + +sp<ColorLayer> RefreshRateSelectionTest::createColorLayer() { + sp<Client> client; + LayerCreationArgs args(mFlinger.flinger(), client, "color-layer", WIDTH, HEIGHT, LAYER_FLAGS, + LayerMetadata()); + return new ColorLayer(args); +} + +void RefreshRateSelectionTest::setParent(Layer* child, Layer* parent) { + child->setParent(parent); +} + +void RefreshRateSelectionTest::commitTransaction(Layer* layer) { + layer->commitTransaction(layer->getCurrentState()); +} + +void RefreshRateSelectionTest::setupScheduler() { + auto eventThread = std::make_unique<mock::EventThread>(); + auto sfEventThread = std::make_unique<mock::EventThread>(); + + EXPECT_CALL(*eventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*eventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(eventThread.get(), ResyncCallback(), + ISurfaceComposer::eConfigChangedSuppress))); + + EXPECT_CALL(*sfEventThread, registerDisplayEventConnection(_)); + EXPECT_CALL(*sfEventThread, createEventConnection(_, _)) + .WillOnce(Return(new EventThreadConnection(sfEventThread.get(), ResyncCallback(), + ISurfaceComposer::eConfigChangedSuppress))); + + auto primaryDispSync = std::make_unique<mock::DispSync>(); + + EXPECT_CALL(*primaryDispSync, computeNextRefresh(0)).WillRepeatedly(Return(0)); + EXPECT_CALL(*primaryDispSync, getPeriod()) + .WillRepeatedly(Return(FakeHwcDisplayInjector::DEFAULT_REFRESH_RATE)); + EXPECT_CALL(*primaryDispSync, expectedPresentTime()).WillRepeatedly(Return(0)); + mFlinger.setupScheduler(std::move(primaryDispSync), + std::make_unique<mock::EventControlThread>(), std::move(eventThread), + std::move(sfEventThread)); +} + +void RefreshRateSelectionTest::setupComposer(int virtualDisplayCount) { + mComposer = new Hwc2::mock::Composer(); + EXPECT_CALL(*mComposer, getCapabilities()) + .WillOnce(Return(std::vector<IComposer::Capability>())); + EXPECT_CALL(*mComposer, getMaxVirtualDisplayCount()).WillOnce(Return(virtualDisplayCount)); + mFlinger.setupComposer(std::unique_ptr<Hwc2::Composer>(mComposer)); + + Mock::VerifyAndClear(mComposer); +} + +namespace { +/* ------------------------------------------------------------------------ + * Test cases + */ +TEST_F(RefreshRateSelectionTest, testPriorityOnBufferQueueLayers) { + mParent = createBufferQueueLayer(); + mChild = createBufferQueueLayer(); + setParent(mChild.get(), mParent.get()); + mGrandChild = createBufferQueueLayer(); + 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, 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, testPriorityOnColorLayers) { + mParent = createColorLayer(); + mChild = createColorLayer(); + setParent(mChild.get(), mParent.get()); + mGrandChild = createColorLayer(); + 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
\ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index f375e23700..1fd0e617c2 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -28,6 +28,7 @@ public: : Layer(LayerCreationArgs(flinger, nullptr, "TestLayer", 800, 600, 0, {})) {} MOCK_CONST_METHOD0(getType, const char*()); + MOCK_METHOD0(getFrameSelectionPriority, int32_t()); MOCK_CONST_METHOD0(isVisible, bool()); MOCK_METHOD0(createClone, sp<Layer>()); }; |