diff options
Diffstat (limited to 'services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp')
-rw-r--r-- | services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp new file mode 100644 index 0000000000..be019848fb --- /dev/null +++ b/services/surfaceflinger/tests/unittests/SurfaceFlinger_SetDisplayStateTest.cpp @@ -0,0 +1,493 @@ +/* + * 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 "DisplayTransactionTestHelpers.h" + +#include <gmock/gmock.h> +#include <gtest/gtest.h> + +namespace android { +namespace { + +class SetDisplayStateLockedTest : public DisplayTransactionTest {}; + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingWithUnknownDisplay) { + // -------------------------------------------------------------------- + // Preconditions + + // We have an unknown display token not associated with a known display + sp<BBinder> displayToken = new BBinder(); + + // The requested display state references the unknown display. + DisplayState state; + state.what = DisplayState::eLayerStackChanged; + state.token = displayToken; + state.layerStack = 456; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags are empty + EXPECT_EQ(0u, flags); + + // The display token still doesn't match anything known. + EXPECT_FALSE(hasCurrentDisplayState(displayToken)); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingWhenNoChanges) { + using Case = SimplePrimaryDisplayCase; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is already set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // No changes are made to the display + DisplayState state; + state.what = 0; + state.token = display.token(); + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags are empty + EXPECT_EQ(0u, flags); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfSurfaceDidNotChange) { + using Case = SimplePrimaryDisplayCase; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is already set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // There is a surface that can be set. + sp<mock::GraphicBufferProducer> surface = new mock::GraphicBufferProducer(); + + // The current display state has the surface set + display.mutableCurrentDisplayState().surface = surface; + + // The incoming request sets the same surface + DisplayState state; + state.what = DisplayState::eSurfaceChanged; + state.token = display.token(); + state.surface = surface; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags are empty + EXPECT_EQ(0u, flags); + + // The current display state is unchanged. + EXPECT_EQ(surface.get(), display.getCurrentDisplayState().surface.get()); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfSurfaceChanged) { + using Case = SimplePrimaryDisplayCase; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is already set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // There is a surface that can be set. + sp<mock::GraphicBufferProducer> surface = new mock::GraphicBufferProducer(); + + // The current display state does not have a surface + display.mutableCurrentDisplayState().surface = nullptr; + + // The incoming request sets a surface + DisplayState state; + state.what = DisplayState::eSurfaceChanged; + state.token = display.token(); + state.surface = surface; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The current display layer stack state is set to the new value + EXPECT_EQ(surface.get(), display.getCurrentDisplayState().surface.get()); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfLayerStackDidNotChange) { + using Case = SimplePrimaryDisplayCase; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is already set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The display has a layer stack set + display.mutableCurrentDisplayState().layerStack = 456u; + + // The incoming request sets the same layer stack + DisplayState state; + state.what = DisplayState::eLayerStackChanged; + state.token = display.token(); + state.layerStack = 456u; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags are empty + EXPECT_EQ(0u, flags); + + // The current display state is unchanged + EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfLayerStackChanged) { + using Case = SimplePrimaryDisplayCase; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The display has a layer stack set + display.mutableCurrentDisplayState().layerStack = 654u; + + // The incoming request sets a different layer stack + DisplayState state; + state.what = DisplayState::eLayerStackChanged; + state.token = display.token(); + state.layerStack = 456u; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The desired display state has been set to the new value. + EXPECT_EQ(456u, display.getCurrentDisplayState().layerStack); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfProjectionDidNotChange) { + using Case = SimplePrimaryDisplayCase; + constexpr ui::Rotation initialOrientation = ui::ROTATION_180; + const Rect initialOrientedDisplayRect = {1, 2, 3, 4}; + const Rect initialLayerStackRect = {5, 6, 7, 8}; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The current display state projection state is all set + display.mutableCurrentDisplayState().orientation = initialOrientation; + display.mutableCurrentDisplayState().orientedDisplaySpaceRect = initialOrientedDisplayRect; + display.mutableCurrentDisplayState().layerStackSpaceRect = initialLayerStackRect; + + // The incoming request sets the same projection state + DisplayState state; + state.what = DisplayState::eDisplayProjectionChanged; + state.token = display.token(); + state.orientation = initialOrientation; + state.orientedDisplaySpaceRect = initialOrientedDisplayRect; + state.layerStackSpaceRect = initialLayerStackRect; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags are empty + EXPECT_EQ(0u, flags); + + // The current display state is unchanged + EXPECT_EQ(initialOrientation, display.getCurrentDisplayState().orientation); + + EXPECT_EQ(initialOrientedDisplayRect, + display.getCurrentDisplayState().orientedDisplaySpaceRect); + EXPECT_EQ(initialLayerStackRect, display.getCurrentDisplayState().layerStackSpaceRect); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfOrientationChanged) { + using Case = SimplePrimaryDisplayCase; + constexpr ui::Rotation initialOrientation = ui::ROTATION_90; + constexpr ui::Rotation desiredOrientation = ui::ROTATION_180; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The current display state has an orientation set + display.mutableCurrentDisplayState().orientation = initialOrientation; + + // The incoming request sets a different orientation + DisplayState state; + state.what = DisplayState::eDisplayProjectionChanged; + state.token = display.token(); + state.orientation = desiredOrientation; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The current display state has the new value. + EXPECT_EQ(desiredOrientation, display.getCurrentDisplayState().orientation); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfFrameChanged) { + using Case = SimplePrimaryDisplayCase; + const Rect initialOrientedDisplayRect = {0, 0, 0, 0}; + const Rect desiredOrientedDisplayRect = {5, 6, 7, 8}; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The current display state does not have a orientedDisplaySpaceRect + display.mutableCurrentDisplayState().orientedDisplaySpaceRect = initialOrientedDisplayRect; + + // The incoming request sets a orientedDisplaySpaceRect + DisplayState state; + state.what = DisplayState::eDisplayProjectionChanged; + state.token = display.token(); + state.orientedDisplaySpaceRect = desiredOrientedDisplayRect; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The current display state has the new value. + EXPECT_EQ(desiredOrientedDisplayRect, + display.getCurrentDisplayState().orientedDisplaySpaceRect); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfLayerStackRectChanged) { + using Case = SimplePrimaryDisplayCase; + const Rect initialLayerStackRect = {0, 0, 0, 0}; + const Rect desiredLayerStackRect = {5, 6, 7, 8}; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The current display state does not have a layerStackSpaceRect + display.mutableCurrentDisplayState().layerStackSpaceRect = initialLayerStackRect; + + // The incoming request sets a layerStackSpaceRect + DisplayState state; + state.what = DisplayState::eDisplayProjectionChanged; + state.token = display.token(); + state.layerStackSpaceRect = desiredLayerStackRect; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The current display state has the new value. + EXPECT_EQ(desiredLayerStackRect, display.getCurrentDisplayState().layerStackSpaceRect); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedDoesNothingIfSizeDidNotChange) { + using Case = SimplePrimaryDisplayCase; + constexpr uint32_t initialWidth = 1024; + constexpr uint32_t initialHeight = 768; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The current display state has a size set + display.mutableCurrentDisplayState().width = initialWidth; + display.mutableCurrentDisplayState().height = initialHeight; + + // The incoming request sets the same display size + DisplayState state; + state.what = DisplayState::eDisplaySizeChanged; + state.token = display.token(); + state.width = initialWidth; + state.height = initialHeight; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags are empty + EXPECT_EQ(0u, flags); + + // The current display state is unchanged + EXPECT_EQ(initialWidth, display.getCurrentDisplayState().width); + EXPECT_EQ(initialHeight, display.getCurrentDisplayState().height); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfWidthChanged) { + using Case = SimplePrimaryDisplayCase; + constexpr uint32_t initialWidth = 0; + constexpr uint32_t desiredWidth = 1024; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The display does not yet have a width + display.mutableCurrentDisplayState().width = initialWidth; + + // The incoming request sets a display width + DisplayState state; + state.what = DisplayState::eDisplaySizeChanged; + state.token = display.token(); + state.width = desiredWidth; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The current display state has the new value. + EXPECT_EQ(desiredWidth, display.getCurrentDisplayState().width); +} + +TEST_F(SetDisplayStateLockedTest, setDisplayStateLockedRequestsUpdateIfHeightChanged) { + using Case = SimplePrimaryDisplayCase; + constexpr uint32_t initialHeight = 0; + constexpr uint32_t desiredHeight = 768; + + // -------------------------------------------------------------------- + // Preconditions + + // A display is set up + auto display = Case::Display::makeFakeExistingDisplayInjector(this); + display.inject(); + + // The display does not yet have a height + display.mutableCurrentDisplayState().height = initialHeight; + + // The incoming request sets a display height + DisplayState state; + state.what = DisplayState::eDisplaySizeChanged; + state.token = display.token(); + state.height = desiredHeight; + + // -------------------------------------------------------------------- + // Invocation + + uint32_t flags = mFlinger.setDisplayStateLocked(state); + + // -------------------------------------------------------------------- + // Postconditions + + // The returned flags indicate a transaction is needed + EXPECT_EQ(eDisplayTransactionNeeded, flags); + + // The current display state has the new value. + EXPECT_EQ(desiredHeight, display.getCurrentDisplayState().height); +} + +} // namespace +} // namespace android |