From 6bd8bfde4a965b743d3d4ebff5fdaa3db03a4bbc Mon Sep 17 00:00:00 2001 From: Marissa Wall Date: Thu, 15 Dec 2016 12:25:31 -0800 Subject: [PATCH] test-hwc2: set layer composition type Test: Add "#define HAVE_NO_SURFACE_FLINGER" to frameworks/native/libs/gui/BufferQueueCore.cpp. Recompile and flash. Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2. Push test-hwc2 to device. Run "adb root && adb shell stop". Run test case. Ex: "./test-hwc2" Change-Id: I9e71d0c01daa70f28031dd8310f2a40d7162a68e --- services/surfaceflinger/tests/hwc2/Android.mk | 5 +- services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 226 +++++++++++++++++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp | 47 +++++ services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h | 44 ++++ .../tests/hwc2/Hwc2TestProperties.cpp | 49 +++++ .../surfaceflinger/tests/hwc2/Hwc2TestProperties.h | 83 ++++++++ 6 files changed, 453 insertions(+), 1 deletion(-) create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp create mode 100644 services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk index 1322293100..66a390df2f 100644 --- a/services/surfaceflinger/tests/hwc2/Android.mk +++ b/services/surfaceflinger/tests/hwc2/Android.mk @@ -27,6 +27,9 @@ LOCAL_CFLAGS += \ -fno-builtin LOCAL_SHARED_LIBRARIES := libcutils libutils libhardware LOCAL_STATIC_LIBRARIES := libbase libadf libadfhwc -LOCAL_SRC_FILES := Hwc2Test.cpp +LOCAL_SRC_FILES := \ + Hwc2Test.cpp \ + Hwc2TestProperties.cpp \ + Hwc2TestLayer.cpp include $(BUILD_NATIVE_TEST) diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index bc3eb1be8b..a50af49ed5 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -26,6 +26,8 @@ #undef HWC2_INCLUDE_STRINGIFICATION #undef HWC2_USE_CPP11 +#include "Hwc2TestLayer.h" + void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData, hwc2_display_t display, int32_t connected); void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, @@ -338,6 +340,23 @@ public: } } + void setLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer, + hwc2_composition_t composition, hwc2_error_t* outErr = nullptr) + { + auto pfn = reinterpret_cast( + getFunction(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE)); + ASSERT_TRUE(pfn) << "failed to get function"; + + auto err = static_cast(pfn(mHwc2Device, display, layer, + composition)); + if (outErr) { + *outErr = err; + } else { + ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer composition" + " type " << getCompositionName(composition); + } + } + protected: hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor) { @@ -475,6 +494,152 @@ protected: *outTimestamp = mVsyncTimestamp; } + /* Calls a set property function from Hwc2Test to set a property value from + * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertyFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + + /* Calls a set property function from Hwc2Test to set a bad property value + * on hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr); + + /* Calls a set property function from Hwc2Test to set a bad property value + * on hwc2_layer_t on hwc2_display_t */ + using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test, + hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr); + + /* Advances a property of Hwc2TestLayer */ + using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer); + + /* For each active display it cycles through each display config and tests + * each property value. It creates a layer, sets the property and then + * destroys the layer */ + void setLayerProperty(Hwc2TestCoverage coverage, + TestLayerPropertyFunction function, AdvanceProperty advance) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + Hwc2TestLayer testLayer(coverage); + + do { + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, nullptr)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } while (advance(&testLayer)); + } + } + } + + /* For each active display it cycles through each display config and tests + * each property value. It creates a layer, cycles through each property + * value and updates the layer property value and then destroys the layer */ + void setLayerPropertyUpdate(Hwc2TestCoverage coverage, + TestLayerPropertyFunction function, AdvanceProperty advance) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + Hwc2TestLayer testLayer(coverage); + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + do { + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, nullptr)); + } while (advance(&testLayer)); + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } + } + } + + /* For each active display it cycles through each display config. + * 1) It attempts to set a valid property value to bad layer handle. + * 2) It creates a layer x and attempts to set a valid property value to + * layer x + 1 + * 3) It destroys the layer x and attempts to set a valid property value to + * the destroyed layer x. + */ + void setLayerPropertyBadLayer(Hwc2TestCoverage coverage, + TestLayerPropertyBadLayerFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer = 0; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + Hwc2TestLayer testLayer(coverage); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1, + testLayer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, + testLayer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code"; + } + } + } + + /* For each active display it cycles through each display config and tests + * each property value. It creates a layer, sets a bad property value and + * then destroys the layer */ + void setLayerPropertyBadParameter(TestLayerPropertyBadParameterFunction function) + { + for (auto display : mDisplays) { + std::vector configs; + + ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs)); + + for (auto config : configs) { + hwc2_layer_t layer; + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config)); + + ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer)); + + ASSERT_NO_FATAL_FAILURE(function(this, display, layer, &err)); + EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong" + " error code"; + + ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer)); + } + } + } + hwc2_device_t* mHwc2Device = nullptr; enum class Hwc2TestHotplugStatus { @@ -518,6 +683,32 @@ void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData, timestamp); } +void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + const Hwc2TestLayer& testLayer, hwc2_error_t* outErr) +{ + hwc2_composition_t composition = testLayer.getComposition(); + hwc2_error_t err = HWC2_ERROR_NONE; + + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer, + composition, &err)); + if (outErr) { + *outErr = err; + return; + } + + if (composition != HWC2_COMPOSITION_SIDEBAND) { + EXPECT_EQ(err, HWC2_ERROR_NONE) << "returned wrong error code"; + } else { + EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED) + << "returned wrong error code"; + } +} + +bool advanceComposition(Hwc2TestLayer* testLayer) +{ + return testLayer->advanceComposition(); +} + static const std::array requiredFunctions = {{ HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES, @@ -1330,3 +1521,38 @@ TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display) ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err)); EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code"; } + +/* TESTCASE: Tests that the HWC2 can set basic composition types. */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE) +{ + ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete, + setComposition, advanceComposition)); +} + +/* TESTCASE: Tests that the HWC2 can update a basic composition type on a + * layer. */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_update) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete, + setComposition, advanceComposition)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a composition type for a bad layer */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_layer) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default, + setComposition)); +} + +/* TESTCASE: Tests that the HWC2 cannot set a bad composition type */ +TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter) +{ + ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter( + [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer, + hwc2_error_t* outErr) { + + ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, + layer, HWC2_COMPOSITION_INVALID, outErr)); + } + )); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp new file mode 100644 index 0000000000..09fb9217b8 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2016 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. + */ + +#include + +#include "Hwc2TestLayer.h" + +Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage) + : mComposition(coverage) { } + +std::string Hwc2TestLayer::dump() const +{ + std::stringstream dmp; + + dmp << "layer: \n"; + dmp << mComposition.dump(); + + return dmp.str(); +} + +void Hwc2TestLayer::reset() +{ + mComposition.reset(); +} + +hwc2_composition_t Hwc2TestLayer::getComposition() const +{ + return mComposition.get(); +} + +bool Hwc2TestLayer::advanceComposition() +{ + return mComposition.advance(); +} diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h new file mode 100644 index 0000000000..9734ab8057 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef _HWC2_TEST_LAYER_H +#define _HWC2_TEST_LAYER_H + +#include "Hwc2TestProperties.h" + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +class Hwc2TestLayer { +public: + Hwc2TestLayer(Hwc2TestCoverage coverage); + + std::string dump() const; + + void reset(); + + hwc2_composition_t getComposition() const; + + bool advanceComposition(); + +private: + Hwc2TestComposition mComposition; +}; + +#endif /* ifndef _HWC2_TEST_LAYER_H */ diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp new file mode 100644 index 0000000000..ef399fd6d4 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2016 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. + */ + +#include + +#include "Hwc2TestProperties.h" + +Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage) + : Hwc2TestProperty( + (coverage == Hwc2TestCoverage::Complete)? mCompleteCompositions: + (coverage == Hwc2TestCoverage::Basic)? mBasicCompositions: + mDefaultCompositions) { } + +std::string Hwc2TestComposition::dump() const +{ + std::stringstream dmp; + dmp << "\tcomposition: " << getCompositionName(get()) << "\n"; + return dmp.str(); +} + +const std::vector Hwc2TestComposition::mDefaultCompositions = { + HWC2_COMPOSITION_DEVICE, +}; + +const std::vector Hwc2TestComposition::mBasicCompositions = { + HWC2_COMPOSITION_CLIENT, + HWC2_COMPOSITION_DEVICE, +}; + +const std::vector Hwc2TestComposition::mCompleteCompositions = { + HWC2_COMPOSITION_CLIENT, + HWC2_COMPOSITION_DEVICE, + HWC2_COMPOSITION_SOLID_COLOR, + HWC2_COMPOSITION_CURSOR, + HWC2_COMPOSITION_SIDEBAND, +}; diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h new file mode 100644 index 0000000000..74f571e140 --- /dev/null +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2016 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. + */ + +#ifndef _HWC2_TEST_PROPERTIES_H +#define _HWC2_TEST_PROPERTIES_H + +#include + +#define HWC2_INCLUDE_STRINGIFICATION +#define HWC2_USE_CPP11 +#include +#undef HWC2_INCLUDE_STRINGIFICATION +#undef HWC2_USE_CPP11 + +enum class Hwc2TestCoverage { + Default = 0, + Basic, + Complete, +}; + + +template +class Hwc2TestProperty { +public: + Hwc2TestProperty(const std::vector& list) + : mList(list) { } + + virtual ~Hwc2TestProperty() { }; + + virtual void reset() + { + mListIdx = 0; + } + + virtual bool advance() + { + if (mListIdx + 1 < mList.size()) { + mListIdx++; + return true; + } + reset(); + return false; + } + + virtual T get() const + { + return mList.at(mListIdx); + } + + virtual std::string dump() const = 0; + +protected: + const std::vector& mList; + size_t mListIdx = 0; +}; + + +class Hwc2TestComposition : public Hwc2TestProperty { +public: + Hwc2TestComposition(Hwc2TestCoverage coverage); + + std::string dump() const override; + +protected: + static const std::vector mDefaultCompositions; + static const std::vector mBasicCompositions; + static const std::vector mCompleteCompositions; +}; + +#endif /* ifndef _HWC2_TEST_PROPERTIES_H */ -- 2.11.0