diff options
| author | 2019-09-25 19:41:30 +0000 | |
|---|---|---|
| committer | 2019-09-25 19:41:30 +0000 | |
| commit | 88d017bfee22b8fc32002d5c1aade750140947cc (patch) | |
| tree | bb3096671f8f846ae94baba75ed6c0a002631627 | |
| parent | 3af10f14f82e1af2c5239bedaffda273b2edc9be (diff) | |
| parent | 9cfc6d81194be7d0bf1c454f7c8b6e678bf87054 (diff) | |
Merge "Refactoring Transaction_test continued"
14 files changed, 5887 insertions, 5596 deletions
diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 7f960f302a..d6b9b60774 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -19,10 +19,19 @@ cc_test { srcs: [ "BufferGenerator.cpp", "Credentials_test.cpp", - "InvalidHandles_test.cpp", - "Stress_test.cpp", + "DereferenceSurfaceControl_test.cpp", + "DisplayActiveConfig_test.cpp", + "InvalidHandles_test.cpp", + "LayerCallback_test.cpp", + "LayerRenderTypeTransaction_test.cpp", + "LayerTransaction_test.cpp", + "LayerTypeAndRenderTypeTransaction_test.cpp", + "LayerTypeTransaction_test.cpp", + "LayerUpdate_test.cpp", + "MultiDisplayLayerBounds_test.cpp", + "RelativeZ_test.cpp", + "Stress_test.cpp", "SurfaceInterceptor_test.cpp", - "Transaction_test.cpp", "VirtualDisplay_test.cpp", ], data: ["SurfaceFlinger_test.filter"], diff --git a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp new file mode 100644 index 0000000000..0cef0d1c87 --- /dev/null +++ b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class DereferenceSurfaceControlTest : public LayerTransactionTest { +protected: + void SetUp() override { + LayerTransactionTest::SetUp(); + bgLayer = createLayer("BG layer", 20, 20); + fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20); + fgLayer = createLayer("FG layer", 20, 20); + fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20); + Transaction().setLayer(fgLayer, mLayerZBase + 1).apply(); + { + SCOPED_TRACE("before anything"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE); + } + } + void TearDown() override { + LayerTransactionTest::TearDown(); + bgLayer = 0; + fgLayer = 0; + } + + sp<SurfaceControl> bgLayer; + sp<SurfaceControl> fgLayer; +}; + +TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) { + fgLayer = nullptr; + { + SCOPED_TRACE("after setting null"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 20, 20), Color::RED); + } +} + +TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) { + auto transaction = Transaction().show(fgLayer); + fgLayer = nullptr; + { + SCOPED_TRACE("after setting null"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE); + } +} + +} // namespace android diff --git a/services/surfaceflinger/tests/DisplayActiveConfig_test.cpp b/services/surfaceflinger/tests/DisplayActiveConfig_test.cpp new file mode 100644 index 0000000000..2e3b760709 --- /dev/null +++ b/services/surfaceflinger/tests/DisplayActiveConfig_test.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <thread> +#include "LayerTransactionTest.h" +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class DisplayActiveConfigTest : public ::testing::Test { +protected: + void SetUp() override { + mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); + SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs); + EXPECT_GT(mDisplayconfigs.size(), 0); + + // set display power to on to make sure config can be changed + SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL); + } + + sp<IBinder> mDisplayToken; + Vector<DisplayInfo> mDisplayconfigs; +}; + +TEST_F(DisplayActiveConfigTest, allConfigsAllowed) { + std::vector<int32_t> allowedConfigs; + + // Add all configs to the allowed configs + for (int i = 0; i < mDisplayconfigs.size(); i++) { + allowedConfigs.push_back(i); + } + + status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); + EXPECT_EQ(res, NO_ERROR); + + std::vector<int32_t> outConfigs; + res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs); + EXPECT_EQ(res, NO_ERROR); + EXPECT_EQ(allowedConfigs, outConfigs); +} + +TEST_F(DisplayActiveConfigTest, changeAllowedConfig) { + // we need at least 2 configs available for this test + if (mDisplayconfigs.size() <= 1) return; + + int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); + + // We want to set the allowed config to everything but the active config + std::vector<int32_t> allowedConfigs; + for (int i = 0; i < mDisplayconfigs.size(); i++) { + if (i != activeConfig) { + allowedConfigs.push_back(i); + } + } + + status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); + EXPECT_EQ(res, NO_ERROR); + + // Allow some time for the config change + std::this_thread::sleep_for(200ms); + + int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); + EXPECT_NE(activeConfig, newActiveConfig); + + // Make sure the new config is part of allowed config + EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) != + allowedConfigs.end()); +} +} // namespace android diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp new file mode 100644 index 0000000000..7a5ed484d1 --- /dev/null +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -0,0 +1,872 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" +#include "utils/CallbackUtils.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class LayerCallbackTest : public LayerTransactionTest { +public: + virtual sp<SurfaceControl> createBufferStateLayer() { + return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState); + } + + static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper, + const sp<SurfaceControl>& layer = nullptr, bool setBuffer = true, + bool setBackgroundColor = false) { + if (layer) { + sp<GraphicBuffer> buffer; + sp<Fence> fence; + if (setBuffer) { + int err = getBuffer(&buffer, &fence); + if (err != NO_ERROR) { + return err; + } + + transaction.setBuffer(layer, buffer); + transaction.setAcquireFence(layer, fence); + } + + if (setBackgroundColor) { + transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f, + ui::Dataspace::UNKNOWN); + } + } + + transaction.addTransactionCompletedCallback(callbackHelper->function, + callbackHelper->getContext()); + return NO_ERROR; + } + + static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult, + bool finalState = false) { + CallbackData callbackData; + ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData)); + EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData)); + + if (finalState) { + ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState()); + } + } + + static void waitForCallbacks(CallbackHelper& helper, + const std::vector<ExpectedResult>& expectedResults, + bool finalState = false) { + for (const auto& expectedResult : expectedResults) { + waitForCallback(helper, expectedResult); + } + if (finalState) { + ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState()); + } + } +}; + +TEST_F(LayerCallbackTest, BufferColor) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer, true, true); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, NoBufferNoColor) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer, false, false); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, BufferNoColor) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer, true, false); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, NoBufferColor) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer, false, true); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, NoStateChange) { + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + + ExpectedResult expected; + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, OffScreen) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, MergeBufferNoColor) { + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} + +TEST_F(LayerCallbackTest, MergeNoBufferColor) { + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + int err = fillTransaction(transaction1, &callback1, layer1, false, true); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2, false, true); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, + ExpectedResult::Buffer::NOT_ACQUIRED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} + +TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2, false, true); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer2, + ExpectedResult::Buffer::NOT_ACQUIRED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} +TEST_F(LayerCallbackTest, Merge_SameCallback) { + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); + + Transaction transaction1, transaction2; + CallbackHelper callback; + int err = fillTransaction(transaction1, &callback, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction2.merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, Merge_SameLayer) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + int err = fillTransaction(transaction1, &callback1, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction2.merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} + +TEST_F(LayerCallbackTest, Merge_DifferentClients) { + sp<SurfaceComposerClient> client1(new SurfaceComposerClient), + client2(new SurfaceComposerClient); + + ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; + ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; + + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} + +TEST_F(LayerCallbackTest, MultipleTransactions) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + for (size_t i = 0; i < 10; i++) { + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::ACQUIRED, + (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED + : ExpectedResult::PreviousBuffer::RELEASED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); + } + ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_NoStateChange) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + for (size_t i = 0; i < 10; i++) { + ExpectedResult expected; + + if (i == 0) { + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + } else { + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + } + + transaction.apply(); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); + } + ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + for (size_t i = 0; i < 10; i++) { + if (i == 0) { + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + } else { + int err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + } + + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + ExpectedResult expected; + expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED + : ExpectedResult::Transaction::NOT_PRESENTED, + layer, + (i == 0) ? ExpectedResult::Buffer::ACQUIRED + : ExpectedResult::Buffer::NOT_ACQUIRED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0)); + } + ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); + ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + for (size_t i = 0; i < 10; i++) { + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, + ExpectedResult::Buffer::ACQUIRED, + (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED + : ExpectedResult::PreviousBuffer::RELEASED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected)); + } + ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState()); + ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState()); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { + sp<SurfaceComposerClient> client1(new SurfaceComposerClient), + client2(new SurfaceComposerClient); + ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; + ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; + + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + for (size_t i = 0; i < 10; i++) { + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, + ExpectedResult::Buffer::ACQUIRED, + (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED + : ExpectedResult::PreviousBuffer::RELEASED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected)); + } + ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState()); + ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState()); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateChange) { + sp<SurfaceComposerClient> client1(new SurfaceComposerClient), + client2(new SurfaceComposerClient); + ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; + ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; + + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + + // Normal call to set up test + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); + expected.reset(); + + // Test + err = fillTransaction(transaction1, &callback1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction2.merge(std::move(transaction1)).apply(); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateChange) { + sp<SurfaceComposerClient> client1(new SurfaceComposerClient), + client2(new SurfaceComposerClient); + + ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; + ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; + + sp<SurfaceControl> layer1, layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, + ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction transaction1, transaction2; + CallbackHelper callback1, callback2; + + // Normal call to set up test + int err = fillTransaction(transaction1, &callback1, layer1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2, layer2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + ExpectedResult expected; + expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); + expected.reset(); + + // Test + err = fillTransaction(transaction1, &callback1); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + err = fillTransaction(transaction2, &callback2); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); + + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, + ExpectedResult::Buffer::NOT_ACQUIRED); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + std::vector<ExpectedResult> expectedResults(50); + for (auto& expected : expectedResults) { + expected.reset(); + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::ACQUIRED, + ExpectedResult::PreviousBuffer::UNKNOWN); + + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + } + EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_NoStateChange) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + // Normal call to set up test + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); + + // Test + std::vector<ExpectedResult> expectedResults(50); + for (auto& expected : expectedResults) { + expected.reset(); + + err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.apply(); + } + EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); +} + +TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + // Normal call to set up test + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + ExpectedResult expectedResult; + expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expectedResult, true)); + + // Test + std::vector<ExpectedResult> expectedResults(50); + for (auto& expected : expectedResults) { + expected.reset(); + expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, + ExpectedResult::Buffer::NOT_ACQUIRED); + + err = fillTransaction(transaction, &callback); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); + } + EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the future + nsecs_t time = systemTime() + (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected.addExpectedPresentTime(time); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback1; + int err = fillTransaction(transaction, &callback1, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the future + nsecs_t time = systemTime() + (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected1; + expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected1.addExpectedPresentTime(time); + + CallbackHelper callback2; + err = fillTransaction(transaction, &callback2, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 33ms after the first frame + time += (33.3 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected2; + expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::ACQUIRED, + ExpectedResult::PreviousBuffer::RELEASED); + expected2.addExpectedPresentTime(time); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback1; + int err = fillTransaction(transaction, &callback1, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the future + nsecs_t time = systemTime() + (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected1; + expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected1.addExpectedPresentTime(time); + + CallbackHelper callback2; + err = fillTransaction(transaction, &callback2, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 33ms before the previous frame + time -= (33.3 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected2; + expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer, + ExpectedResult::Buffer::ACQUIRED, + ExpectedResult::PreviousBuffer::RELEASED); + + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true)); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true)); +} + +TEST_F(LayerCallbackTest, DesiredPresentTime_Past) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); + + Transaction transaction; + CallbackHelper callback; + int err = fillTransaction(transaction, &callback, layer); + if (err) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + // Try to present 100ms in the past + nsecs_t time = systemTime() - (100 * 1e6); + + transaction.setDesiredPresentTime(time); + transaction.apply(); + + ExpectedResult expected; + expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); + expected.addExpectedPresentTime(systemTime()); + EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); +} +} // namespace android diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp new file mode 100644 index 0000000000..a48f553d74 --- /dev/null +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -0,0 +1,1834 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/BufferItemConsumer.h> +#include <thread> +#include "TransactionTestHarnesses.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class LayerRenderTypeTransactionTest : public LayerTransactionTest, + public ::testing::WithParamInterface<RenderPath> { +public: + LayerRenderTypeTransactionTest() : mHarness(LayerRenderPathTestHarness(this, GetParam())) {} + + std::unique_ptr<ScreenCapture> getScreenCapture() { return mHarness.getScreenCapture(); } + void setRelativeZBasicHelper(uint32_t layerType); + void setRelativeZGroupHelper(uint32_t layerType); + void setAlphaBasicHelper(uint32_t layerType); + void setBackgroundColorHelper(uint32_t layerType, bool priorColor, bool bufferFill, float alpha, + Color finalColor); + +protected: + LayerRenderPathTestHarness mHarness; +}; + +INSTANTIATE_TEST_CASE_P(LayerRenderTypeTransactionTests, LayerRenderTypeTransactionTest, + ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT)); + +TEST_P(LayerRenderTypeTransactionTest, SetPositionBasic_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("default position"); + const Rect rect(0, 0, 32, 32); + auto shot = getScreenCapture(); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } + + Transaction().setPosition(layer, 5, 10).apply(); + { + SCOPED_TRACE("new position"); + const Rect rect(5, 10, 37, 42); + auto shot = getScreenCapture(); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetPositionRounding_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // GLES requires only 4 bits of subpixel precision during rasterization + // XXX GLES composition does not match HWC composition due to precision + // loss (b/69315223) + const float epsilon = 1.0f / 16.0f; + Transaction().setPosition(layer, 0.5f - epsilon, 0.5f - epsilon).apply(); + { + SCOPED_TRACE("rounding down"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + Transaction().setPosition(layer, 0.5f + epsilon, 0.5f + epsilon).apply(); + { + SCOPED_TRACE("rounding up"); + getScreenCapture()->expectColor(Rect(1, 1, 33, 33), Color::RED); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetPositionOutOfBounds_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setPosition(layer, -32, -32).apply(); + { + SCOPED_TRACE("negative coordinates"); + getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); + } + + Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply(); + { + SCOPED_TRACE("positive coordinates"); + getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetPositionPartiallyOutOfBounds_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // partially out of bounds + Transaction().setPosition(layer, -30, -30).apply(); + { + SCOPED_TRACE("negative coordinates"); + getScreenCapture()->expectColor(Rect(0, 0, 2, 2), Color::RED); + } + + Transaction().setPosition(layer, mDisplayWidth - 2, mDisplayHeight - 2).apply(); + { + SCOPED_TRACE("positive coordinates"); + getScreenCapture()->expectColor(Rect(mDisplayWidth - 2, mDisplayHeight - 2, mDisplayWidth, + mDisplayHeight), + Color::RED); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetPositionWithResize_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // setPosition is applied immediately by default, with or without resize + // pending + Transaction().setPosition(layer, 5, 10).setSize(layer, 64, 64).apply(); + { + SCOPED_TRACE("resize pending"); + auto shot = getScreenCapture(); + const Rect rect(5, 10, 37, 42); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); + { + SCOPED_TRACE("resize applied"); + getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setSize(layer, 64, 64).apply(); + { + SCOPED_TRACE("resize pending"); + auto shot = getScreenCapture(); + const Rect rect(0, 0, 32, 32); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); + { + SCOPED_TRACE("resize applied"); + auto shot = getScreenCapture(); + const Rect rect(0, 0, 64, 64); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition + Transaction() + .setSize(layer, 64, 64) + .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) + .apply(); + getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED); +} + +void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) { + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32)); + + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + Transaction() + .setPosition(layerG, 16, 16) + .setRelativeLayer(layerG, layerR->getHandle(), 1) + .apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(16, 16, 48, 48)) + .setRelativeLayer(layerG, layerR->getHandle(), 1) + .apply(); + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + { + SCOPED_TRACE("layerG above"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 16, 16), Color::RED); + shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN); + } + + Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply(); + { + SCOPED_TRACE("layerG below"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectColor(Rect(32, 32, 48, 48), Color::GREEN); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferQueue) { + ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferState) { + ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) { + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + sp<SurfaceControl> layerB; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerB, Color::BLUE, 32, 32)); + + // layerR = 0, layerG = layerR + 3, layerB = 2 + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + Transaction() + .setPosition(layerG, 8, 8) + .setRelativeLayer(layerG, layerR->getHandle(), 3) + .setPosition(layerB, 16, 16) + .setLayer(layerB, mLayerZBase + 2) + .apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + Transaction() + .setFrame(layerR, Rect(0, 0, 32, 32)) + .setFrame(layerG, Rect(8, 8, 40, 40)) + .setRelativeLayer(layerG, layerR->getHandle(), 3) + .setFrame(layerB, Rect(16, 16, 48, 48)) + .setLayer(layerB, mLayerZBase + 2) + .apply(); + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + + { + SCOPED_TRACE("(layerR < layerG) < layerB"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 8, 8), Color::RED); + shot->expectColor(Rect(8, 8, 16, 16), Color::GREEN); + shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE); + } + + // layerR = 4, layerG = layerR + 3, layerB = 2 + Transaction().setLayer(layerR, mLayerZBase + 4).apply(); + { + SCOPED_TRACE("layerB < (layerR < layerG)"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 8, 8), Color::RED); + shot->expectColor(Rect(8, 8, 40, 40), Color::GREEN); + shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE); + } + + // layerR = 4, layerG = layerR - 3, layerB = 2 + Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply(); + { + SCOPED_TRACE("layerB < (layerG < layerR)"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectColor(Rect(32, 32, 40, 40), Color::GREEN); + shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE); + } + + // restore to absolute z + // layerR = 4, layerG = 0, layerB = 2 + Transaction().setLayer(layerG, mLayerZBase).apply(); + { + SCOPED_TRACE("layerG < layerB < layerR"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectColor(Rect(32, 32, 48, 48), Color::BLUE); + } + + // layerR should not affect layerG anymore + // layerR = 1, layerG = 0, layerB = 2 + Transaction().setLayer(layerR, mLayerZBase + 1).apply(); + { + SCOPED_TRACE("layerG < layerR < layerB"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 16, 16), Color::RED); + shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferQueue) { + ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferState) { + ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferQueue) { + const Rect top(0, 0, 32, 16); + const Rect bottom(0, 16, 32, 32); + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + + ANativeWindow_Buffer buffer; + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE( + TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE( + TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::RED)); + // setTransparentRegionHint always applies to the following buffer + Transaction().setTransparentRegionHint(layer, Region(top)).apply(); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); + { + SCOPED_TRACE("top transparent"); + auto shot = getScreenCapture(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::RED); + } + + Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); + { + SCOPED_TRACE("transparent region hint pending"); + auto shot = getScreenCapture(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_NO_FATAL_FAILURE( + TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE( + TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); + { + SCOPED_TRACE("bottom transparent"); + auto shot = getScreenCapture(); + shot->expectColor(top, Color::RED); + shot->expectColor(bottom, Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState) { + const Rect top(0, 0, 32, 16); + const Rect bottom(0, 16, 32, 32); + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE( + TransactionUtils::fillGraphicBufferColor(buffer, top, Color::TRANSPARENT)); + ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::RED)); + Transaction() + .setTransparentRegionHint(layer, Region(top)) + .setBuffer(layer, buffer) + .setFrame(layer, Rect(0, 0, 32, 32)) + .apply(); + { + SCOPED_TRACE("top transparent"); + auto shot = getScreenCapture(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::RED); + } + + Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); + { + SCOPED_TRACE("transparent region hint intermediate"); + auto shot = getScreenCapture(); + shot->expectColor(top, Color::BLACK); + shot->expectColor(bottom, Color::BLACK); + } + + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, top, Color::RED)); + ASSERT_NO_FATAL_FAILURE( + TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT)); + Transaction().setBuffer(layer, buffer).apply(); + { + SCOPED_TRACE("bottom transparent"); + auto shot = getScreenCapture(); + shot->expectColor(top, Color::RED); + shot->expectColor(bottom, Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferQueue) { + sp<SurfaceControl> layerTransparent; + sp<SurfaceControl> layerR; + ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + + // check that transparent region hint is bound by the layer size + Transaction() + .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) + .setPosition(layerR, 16, 16) + .setLayer(layerR, mLayerZBase + 1) + .apply(); + ASSERT_NO_FATAL_FAILURE( + fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layerR, Color::RED, 32, 32)); + getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED); +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferState) { + sp<SurfaceControl> layerTransparent; + sp<SurfaceControl> layerR; + ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); + ASSERT_NO_FATAL_FAILURE( + layerR = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + // check that transparent region hint is bound by the layer size + Transaction() + .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) + .setFrame(layerR, Rect(16, 16, 48, 48)) + .setLayer(layerR, mLayerZBase + 1) + .apply(); + ASSERT_NO_FATAL_FAILURE( + fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32)); + getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED); +} + +void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { + sp<SurfaceControl> layer1; + sp<SurfaceControl> layer2; + ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32, layerType)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer1, {64, 0, 0, 255}, 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer2, {0, 64, 0, 255}, 32, 32)); + + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + Transaction() + .setAlpha(layer1, 0.25f) + .setAlpha(layer2, 0.75f) + .setPosition(layer2, 16, 0) + .setLayer(layer2, mLayerZBase + 1) + .apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + Transaction() + .setAlpha(layer1, 0.25f) + .setAlpha(layer2, 0.75f) + .setFrame(layer1, Rect(0, 0, 32, 32)) + .setFrame(layer2, Rect(16, 0, 48, 32)) + .setLayer(layer2, mLayerZBase + 1) + .apply(); + break; + default: + ASSERT_FALSE(true) << "Unsupported layer type"; + } + { + auto shot = getScreenCapture(); + uint8_t r = 16; // 64 * 0.25f + uint8_t g = 48; // 64 * 0.75f + shot->expectColor(Rect(0, 0, 16, 32), {r, 0, 0, 255}); + shot->expectColor(Rect(32, 0, 48, 32), {0, g, 0, 255}); + + r /= 4; // r * (1.0f - 0.75f) + shot->expectColor(Rect(16, 0, 32, 32), {r, g, 0, 255}); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferQueue) { + ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferState) { + ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorBasic) { + sp<SurfaceControl> bufferLayer; + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + + Transaction() + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setLayer(colorLayer, mLayerZBase + 1) + .apply(); + + { + SCOPED_TRACE("default color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); + const Color expected = {15, 51, 85, 255}; + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + Transaction().setColor(colorLayer, color).apply(); + { + SCOPED_TRACE("new color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expected, tolerance); + } +} + +// RED: Color layer base color and BufferQueueLayer/BufferStateLayer fill +// BLUE: prior background color +// GREEN: final background color +// BLACK: no color or fill +void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType, bool priorColor, + bool bufferFill, float alpha, + Color finalColor) { + sp<SurfaceControl> layer; + int32_t width = 500; + int32_t height = 500; + + Color fillColor = Color::RED; + Color priorBgColor = Color::BLUE; + Color expectedColor = Color::BLACK; + switch (layerType) { + case ISurfaceComposerClient::eFXSurfaceColor: + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 0, 0, layerType)); + Transaction() + .setCrop_legacy(layer, Rect(0, 0, width, height)) + .setColor(layer, half3(1.0f, 0, 0)) + .apply(); + expectedColor = fillColor; + break; + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height)); + if (bufferFill) { + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, fillColor, width, height)); + expectedColor = fillColor; + } + Transaction().setCrop_legacy(layer, Rect(0, 0, width, height)).apply(); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, layerType)); + if (bufferFill) { + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); + expectedColor = fillColor; + } + Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); + break; + default: + GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; + return; + } + + if (priorColor && layerType != ISurfaceComposerClient::eFXSurfaceColor) { + Transaction() + .setBackgroundColor(layer, half3(0, 0, 1.0f), 1.0f, ui::Dataspace::UNKNOWN) + .apply(); + if (!bufferFill) { + expectedColor = priorBgColor; + } + } + + { + SCOPED_TRACE("default before setting background color layer"); + screenshot()->expectColor(Rect(0, 0, width, height), expectedColor); + } + Transaction() + .setBackgroundColor(layer, half3(0, 1.0f, 0), alpha, ui::Dataspace::UNKNOWN) + .apply(); + + { + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, width, height), finalColor); + shot->expectBorder(Rect(0, 0, width, height), Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_Color_NoEffect) { + bool priorColor = false; + bool bufferFill = false; + float alpha = 1.0f; + Color finalColor = Color::RED; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceColor, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferQueue_BufferFill_NoPriorColor_Basic) { + bool priorColor = false; + bool bufferFill = true; + float alpha = 1.0f; + Color finalColor = Color::RED; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferQueue_NoBufferFill_NoPriorColor_Basic) { + bool priorColor = false; + bool bufferFill = false; + float alpha = 1.0f; + Color finalColor = Color::GREEN; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferQueue_BufferFill_PriorColor_Basic) { + bool priorColor = true; + bool bufferFill = true; + float alpha = 1.0f; + Color finalColor = Color::RED; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferQueue_NoBufferFill_PriorColor_Basic) { + bool priorColor = true; + bool bufferFill = false; + float alpha = 1.0f; + Color finalColor = Color::GREEN; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, + priorColor, bufferFill, alpha, finalColor)); +} +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferQueue_NoPriorColor_ZeroAlpha_NoEffect) { + bool priorColor = false; + bool bufferFill = false; + float alpha = 0; + Color finalColor = Color::BLACK; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferQueue_PriorColor_ZeroAlpha_DeleteBackground) { + bool priorColor = true; + bool bufferFill = false; + float alpha = 0; + Color finalColor = Color::BLACK; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferState_BufferFill_NoPriorColor_Basic) { + bool priorColor = false; + bool bufferFill = true; + float alpha = 1.0f; + Color finalColor = Color::RED; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferState_NoBufferFill_NoPriorColor_Basic) { + bool priorColor = false; + bool bufferFill = false; + float alpha = 1.0f; + Color finalColor = Color::GREEN; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferState_NoBufferFill_PriorColor_Basic) { + bool priorColor = true; + bool bufferFill = false; + float alpha = 1.0f; + Color finalColor = Color::GREEN; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferState_NoPriorColor_ZeroAlpha_NoEffect) { + bool priorColor = false; + bool bufferFill = false; + float alpha = 0; + Color finalColor = Color::BLACK; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, + SetBackgroundColor_BufferState_PriorColor_ZeroAlpha_DeleteBackground) { + bool priorColor = true; + bool bufferFill = false; + float alpha = 0; + Color finalColor = Color::BLACK; + ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, + priorColor, bufferFill, alpha, finalColor)); +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorClamped) { + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction() + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)) + .apply(); + + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorWithAlpha) { + sp<SurfaceControl> bufferLayer; + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply(); + + const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); + const float alpha = 0.25f; + const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f); + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + Transaction() + .setColor(colorLayer, color) + .setAlpha(colorLayer, alpha) + .setLayer(colorLayer, mLayerZBase + 1) + .apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255}, + tolerance); +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorWithParentAlpha_Bug74220420) { + sp<SurfaceControl> bufferLayer; + sp<SurfaceControl> parentLayer; + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); + ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer("childWithColor", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply(); + const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); + const float alpha = 0.25f; + const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f); + // this is handwavy, but the precision loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + Transaction() + .reparent(colorLayer, parentLayer->getHandle()) + .setColor(colorLayer, color) + .setAlpha(parentLayer, alpha) + .setLayer(parentLayer, mLayerZBase + 1) + .apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255}, + tolerance); +} + +TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply(); + { + SCOPED_TRACE("IDENTITY"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); + } + + Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 32, 0).apply(); + { + SCOPED_TRACE("FLIP_H"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, + Color::WHITE, Color::BLUE); + } + + Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).setPosition(layer, 0, 32).apply(); + { + SCOPED_TRACE("FLIP_V"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, + Color::RED, Color::GREEN); + } + + Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).setPosition(layer, 32, 0).apply(); + { + SCOPED_TRACE("ROT_90"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, + Color::WHITE, Color::GREEN); + } + + Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setPosition(layer, 0, 0).apply(); + { + SCOPED_TRACE("SCALE"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 64), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE, true /* filtered */); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction() + .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) + .setFrame(layer, Rect(0, 0, 32, 32)) + .apply(); + { + SCOPED_TRACE("IDENTITY"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); + } + + Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); + { + SCOPED_TRACE("FLIP_H"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); + } + + Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); + { + SCOPED_TRACE("FLIP_V"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); + } + + Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); + { + SCOPED_TRACE("ROT_90"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); + } + + Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); + { + SCOPED_TRACE("SCALE"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetMatrixRot45_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + const float rot = M_SQRT1_2; // 45 degrees + const float trans = M_SQRT2 * 16.0f; + Transaction().setMatrix(layer, rot, rot, -rot, rot).setPosition(layer, trans, 0).apply(); + + auto shot = getScreenCapture(); + // check a 8x8 region inside each color + auto get8x8Rect = [](int32_t centerX, int32_t centerY) { + const int32_t halfL = 4; + return Rect(centerX - halfL, centerY - halfL, centerX + halfL, centerY + halfL); + }; + const int32_t unit = int32_t(trans / 2); + shot->expectColor(get8x8Rect(2 * unit, 1 * unit), Color::RED); + shot->expectColor(get8x8Rect(3 * unit, 2 * unit), Color::GREEN); + shot->expectColor(get8x8Rect(1 * unit, 2 * unit), Color::BLUE); + shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE); +} + +TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithResize_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // setMatrix is applied after any pending resize, unlike setPosition + Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply(); + { + SCOPED_TRACE("resize pending"); + auto shot = getScreenCapture(); + const Rect rect(0, 0, 32, 32); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); + { + SCOPED_TRACE("resize applied"); + const Rect rect(0, 0, 128, 128); + getScreenCapture()->expectColor(rect, Color::RED); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition + Transaction() + .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) + .setSize(layer, 64, 64) + .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) + .apply(); + getScreenCapture()->expectColor(Rect(0, 0, 128, 128), Color::RED); +} + +TEST_P(LayerRenderTypeTransactionTest, SetOverrideScalingModeBasic_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + // XXX SCALE_CROP is not respected; calling setSize and + // setOverrideScalingMode in separate transactions does not work + // (b/69315456) + Transaction() + .setSize(layer, 64, 16) + .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) + .apply(); + { + SCOPED_TRACE("SCALE_TO_WINDOW"); + getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE, true /* filtered */); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + const Rect crop(8, 8, 24, 24); + + Transaction().setCrop_legacy(layer, crop).apply(); + auto shot = getScreenCapture(); + shot->expectColor(crop, Color::RED); + shot->expectBorder(crop, Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect crop(8, 8, 24, 24); + + Transaction().setCrop(layer, crop).apply(); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("empty rect"); + Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + { + SCOPED_TRACE("negative rect"); + Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("empty rect"); + Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + } + + { + SCOPED_TRACE("negative rect"); + Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 64, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); + + Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); + + Transaction().setBuffer(layer, buffer).apply(); + + // Partially out of bounds in the negative (upper left) direction + Transaction().setCrop(layer, Rect(-128, -128, 32, 16)).apply(); + { + SCOPED_TRACE("out of bounds, negative (upper left) direction"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + } + + // Partially out of bounds in the positive (lower right) direction + Transaction().setCrop(layer, Rect(0, 16, 128, 128)).apply(); + { + SCOPED_TRACE("out of bounds, positive (lower right) direction"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + } + + // Fully out of buffer space bounds + Transaction().setCrop(layer, Rect(-128, -128, -1, -1)).apply(); + { + SCOPED_TRACE("Fully out of bounds"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); + shot->expectColor(Rect(0, 16, 64, 64), Color::RED); + shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + const Point position(32, 32); + const Rect crop(8, 8, 24, 24); + Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply(); + auto shot = getScreenCapture(); + shot->expectColor(crop + position, Color::RED); + shot->expectBorder(crop + position, Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + const Rect frame(32, 32, 64, 64); + const Rect crop(8, 8, 24, 24); + Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); + auto shot = getScreenCapture(); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // crop_legacy is affected by matrix + Transaction() + .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) + .setCrop_legacy(layer, Rect(8, 8, 24, 24)) + .apply(); + auto shot = getScreenCapture(); + shot->expectColor(Rect(16, 16, 48, 48), Color::RED); + shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetCropWithResize_BufferQueue) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + // setCrop_legacy is applied immediately by default, with or without resize pending + Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); + { + SCOPED_TRACE("resize pending"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(8, 8, 24, 24), Color::RED); + shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); + { + SCOPED_TRACE("resize applied"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(8, 8, 16, 16), Color::RED); + shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + const Rect frame(8, 8, 24, 24); + + Transaction().setFrame(layer, frame).apply(); + auto shot = getScreenCapture(); + shot->expectColor(frame, Color::RED); + shot->expectBorder(frame, Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("empty rect"); + Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + { + SCOPED_TRACE("negative rect"); + Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); + + // A parentless layer will default to a frame with the same size as the buffer + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { + sp<SurfaceControl> parent, child; + ASSERT_NO_FATAL_FAILURE( + parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); + + ASSERT_NO_FATAL_FAILURE( + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); + + Transaction().reparent(child, parent->getHandle()).apply(); + + // A layer will default to the frame of its parent + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { + sp<SurfaceControl> parent, child; + ASSERT_NO_FATAL_FAILURE(parent = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); + + ASSERT_NO_FATAL_FAILURE( + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); + + Transaction().reparent(child, parent->getHandle()).apply(); + + // A layer will default to the frame of its parent + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); + + std::this_thread::sleep_for(500ms); + + Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(16, 16, 48, 48), Color::RED); + shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { + sp<SurfaceControl> parent, child; + ASSERT_NO_FATAL_FAILURE( + parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + ASSERT_NO_FATAL_FAILURE( + child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + Transaction().reparent(child, parent->getHandle()).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); + Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); + Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 16), Color::RED); + shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); + shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 1"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); + + { + SCOPED_TRACE("set buffer 2"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); + + { + SCOPED_TRACE("set buffer 3"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { + sp<SurfaceControl> layer1; + ASSERT_NO_FATAL_FAILURE( + layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<SurfaceControl> layer2; + ASSERT_NO_FATAL_FAILURE( + layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); + + Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); + { + SCOPED_TRACE("set layer 1 buffer red"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 64, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); + + Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); + { + SCOPED_TRACE("set layer 2 buffer blue"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::RED); + shot->expectColor(Rect(0, 32, 32, 64), Color::RED); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64)); + { + SCOPED_TRACE("set layer 1 buffer green"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32)); + + { + SCOPED_TRACE("set layer 2 buffer white"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE); + shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); + shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN}; + + std::array<sp<GraphicBuffer>, 10> buffers; + + size_t idx = 0; + for (auto& buffer : buffers) { + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + Color color = colors[idx % colors.size()]; + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); + idx++; + } + + // Set each buffer twice. The first time adds it to the cache, the second time tests that the + // cache is working. + idx = 0; + for (auto& buffer : buffers) { + for (int i = 0; i < 2; i++) { + Transaction().setBuffer(layer, buffer).apply(); + + Color color = colors[idx % colors.size()]; + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + } + idx++; + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN}; + + std::array<sp<GraphicBuffer>, 70> buffers; + + size_t idx = 0; + for (auto& buffer : buffers) { + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + Color color = colors[idx % colors.size()]; + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); + idx++; + } + + // Set each buffer twice. The first time adds it to the cache, the second time tests that the + // cache is working. + idx = 0; + for (auto& buffer : buffers) { + for (int i = 0; i < 2; i++) { + Transaction().setBuffer(layer, buffer).apply(); + + Color color = colors[idx % colors.size()]; + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + } + idx++; + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN}; + + std::array<sp<GraphicBuffer>, 65> buffers; + + size_t idx = 0; + for (auto& buffer : buffers) { + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + Color color = colors[idx % colors.size()]; + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); + idx++; + } + + // Set each buffer twice. The first time adds it to the cache, the second time tests that the + // cache is working. + idx = 0; + for (auto& buffer : buffers) { + for (int i = 0; i < 2; i++) { + Transaction().setBuffer(layer, buffer).apply(); + + Color color = colors[idx % colors.size()]; + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); + } + if (idx == 0) { + buffers[0].clear(); + } + idx++; + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) + .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) + .apply(); + + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE, + Color::GREEN, true /* filtered */); +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) + .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) + .apply(); + + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE, + Color::BLUE, true /* filtered */); +} + +TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, + Color::BLUE, Color::WHITE)); + + Transaction() + .setFrame(layer, Rect(0, 0, 32, 32)) + .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) + .apply(); + + getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED, + Color::GREEN, true /* filtered */); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFenceBasic_BufferState) { + sp<SurfaceControl> layer; + Transaction transaction; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + sp<Fence> fence; + if (getBuffer(nullptr, &fence) != NO_ERROR) { + GTEST_SUCCEED() << "test not supported"; + return; + } + + Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); + + status_t status = fence->wait(1000); + ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status); + std::this_thread::sleep_for(200ms); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + sp<Fence> fence = Fence::NO_FENCE; + + Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + HdrMetadata hdrMetadata; + hdrMetadata.validTypes = 0; + Transaction().setBuffer(layer, buffer).setHdrMetadata(layer, hdrMetadata).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Region region; + region.set(32, 32); + Transaction().setBuffer(layer, buffer).setSurfaceDamageRegion(layer, region).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + sp<GraphicBuffer> buffer = + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); + + Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); + + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); + shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(colorLayer = + createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor)); + Transaction() + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setLayer(colorLayer, mLayerZBase + 1) + .apply(); + { + SCOPED_TRACE("default color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); + half3 expected = color; + mat3 matrix; + matrix[0][0] = 0.3; + matrix[1][0] = 0.59; + matrix[2][0] = 0.11; + matrix[0][1] = 0.3; + matrix[1][1] = 0.59; + matrix[2][1] = 0.11; + matrix[0][2] = 0.3; + matrix[1][2] = 0.59; + matrix[2][2] = 0.11; + + // degamma before applying the matrix + if (mColorManagementUsed) { + ColorTransformHelper::DegammaColor(expected); + } + + ColorTransformHelper::applyMatrix(expected, matrix); + + if (mColorManagementUsed) { + ColorTransformHelper::GammaColor(expected); + } + + const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255), + uint8_t(expected.b * 255), 255}; + + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + + Transaction().setColor(colorLayer, color).setColorTransform(colorLayer, matrix, vec3()).apply(); + { + SCOPED_TRACE("new color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnParent) { + sp<SurfaceControl> parentLayer; + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceContainer)); + ASSERT_NO_FATAL_FAILURE( + colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get())); + + Transaction() + .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100)) + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setLayer(parentLayer, mLayerZBase + 1) + .apply(); + { + SCOPED_TRACE("default color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); + half3 expected = color; + mat3 matrix; + matrix[0][0] = 0.3; + matrix[1][0] = 0.59; + matrix[2][0] = 0.11; + matrix[0][1] = 0.3; + matrix[1][1] = 0.59; + matrix[2][1] = 0.11; + matrix[0][2] = 0.3; + matrix[1][2] = 0.59; + matrix[2][2] = 0.11; + + // degamma before applying the matrix + if (mColorManagementUsed) { + ColorTransformHelper::DegammaColor(expected); + } + + ColorTransformHelper::applyMatrix(expected, matrix); + + if (mColorManagementUsed) { + ColorTransformHelper::GammaColor(expected); + } + + const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255), + uint8_t(expected.b * 255), 255}; + + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + + Transaction() + .setColor(colorLayer, color) + .setColorTransform(parentLayer, matrix, vec3()) + .apply(); + { + SCOPED_TRACE("new color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance); + } +} + +TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnChildAndParent) { + sp<SurfaceControl> parentLayer; + sp<SurfaceControl> colorLayer; + ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceContainer)); + ASSERT_NO_FATAL_FAILURE( + colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get())); + + Transaction() + .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100)) + .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) + .setLayer(parentLayer, mLayerZBase + 1) + .apply(); + { + SCOPED_TRACE("default color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); + half3 expected = color; + mat3 matrixChild; + matrixChild[0][0] = 0.3; + matrixChild[1][0] = 0.59; + matrixChild[2][0] = 0.11; + matrixChild[0][1] = 0.3; + matrixChild[1][1] = 0.59; + matrixChild[2][1] = 0.11; + matrixChild[0][2] = 0.3; + matrixChild[1][2] = 0.59; + matrixChild[2][2] = 0.11; + mat3 matrixParent; + matrixParent[0][0] = 0.2; + matrixParent[1][0] = 0.4; + matrixParent[2][0] = 0.10; + matrixParent[0][1] = 0.2; + matrixParent[1][1] = 0.4; + matrixParent[2][1] = 0.10; + matrixParent[0][2] = 0.2; + matrixParent[1][2] = 0.4; + matrixParent[2][2] = 0.10; + + // degamma before applying the matrix + if (mColorManagementUsed) { + ColorTransformHelper::DegammaColor(expected); + } + + ColorTransformHelper::applyMatrix(expected, matrixChild); + ColorTransformHelper::applyMatrix(expected, matrixParent); + + if (mColorManagementUsed) { + ColorTransformHelper::GammaColor(expected); + } + + const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255), + uint8_t(expected.b * 255), 255}; + + // this is handwavy, but the precison loss scaled by 255 (8-bit per + // channel) should be less than one + const uint8_t tolerance = 1; + + Transaction() + .setColor(colorLayer, color) + .setColorTransform(parentLayer, matrixParent, vec3()) + .setColorTransform(colorLayer, matrixChild, vec3()) + .apply(); + { + SCOPED_TRACE("new color"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance); + } +} +} // namespace android diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h new file mode 100644 index 0000000000..7edddb6ea3 --- /dev/null +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_LAYER_TRANSACTION_TEST_H +#define ANDROID_LAYER_TRANSACTION_TEST_H + +#include <gtest/gtest.h> + +#include <gui/ISurfaceComposer.h> +#include <gui/SurfaceComposerClient.h> +#include <hardware/hwcomposer_defs.h> +#include <private/gui/ComposerService.h> + +#include <ui/DisplayInfo.h> + +#include "BufferGenerator.h" +#include "utils/ScreenshotUtils.h" +#include "utils/TransactionUtils.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +class LayerTransactionTest : public ::testing::Test { +protected: + void SetUp() override { + mClient = new SurfaceComposerClient; + ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient"; + + ASSERT_NO_FATAL_FAILURE(SetUpDisplay()); + + sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed)); + } + + virtual void TearDown() { + mBlackBgSurface = 0; + mClient->dispose(); + mClient = 0; + } + + virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client, + const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0, SurfaceControl* parent = nullptr) { + auto layer = + createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags, parent); + + Transaction t; + t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase); + + status_t error = t.apply(); + if (error != NO_ERROR) { + ADD_FAILURE() << "failed to initialize SurfaceControl"; + layer.clear(); + } + + return layer; + } + + virtual sp<SurfaceControl> createSurface(const sp<SurfaceComposerClient>& client, + const char* name, uint32_t width, uint32_t height, + PixelFormat format, uint32_t flags, + SurfaceControl* parent = nullptr) { + auto layer = client->createSurface(String8(name), width, height, format, flags, parent); + EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; + return layer; + } + + virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0, SurfaceControl* parent = nullptr) { + return createLayer(mClient, name, width, height, flags, parent); + } + + sp<SurfaceControl> createColorLayer(const char* name, const Color& color, + SurfaceControl* parent = nullptr) { + auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, parent); + asTransaction([&](Transaction& t) { + t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f}); + t.setAlpha(colorLayer, color.a / 255.0f); + }); + return colorLayer; + } + + ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { + // wait for previous transactions (such as setSize) to complete + Transaction().apply(true); + + ANativeWindow_Buffer buffer = {}; + EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr)); + + return buffer; + } + + void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { + ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost()); + + // wait for the newly posted buffer to be latched + waitForLayerBuffers(); + } + + virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + ANativeWindow_Buffer buffer; + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + TransactionUtils::fillANativeWindowBufferColor(buffer, + Rect(0, 0, bufferWidth, bufferHeight), + color); + postBufferQueueLayerBuffer(layer); + } + + virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + sp<GraphicBuffer> buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), + color); + Transaction().setBuffer(layer, buffer).apply(); + } + + void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color, + int32_t bufferWidth, int32_t bufferHeight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } + } + + void fillLayerQuadrant(uint32_t mLayerType, const sp<SurfaceControl>& layer, + int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { + switch (mLayerType) { + case ISurfaceComposerClient::eFXSurfaceBufferQueue: + fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + case ISurfaceComposerClient::eFXSurfaceBufferState: + fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, + bottomLeft, bottomRight); + break; + default: + ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; + } + } + + virtual void fillBufferQueueLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { + ANativeWindow_Buffer buffer; + ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), + topRight); + TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), + bottomLeft); + TransactionUtils::fillANativeWindowBufferColor(buffer, + Rect(halfW, halfH, bufferWidth, + bufferHeight), + bottomRight); + + postBufferQueueLayerBuffer(layer); + } + + virtual void fillBufferStateLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, + const Color& topRight, const Color& bottomLeft, + const Color& bottomRight) { + sp<GraphicBuffer> buffer = + new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, + BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | + BufferUsage::COMPOSER_OVERLAY, + "test"); + + ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); + + const int32_t halfW = bufferWidth / 2; + const int32_t halfH = bufferHeight / 2; + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), + topRight); + TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), + bottomLeft); + TransactionUtils::fillGraphicBufferColor(buffer, + Rect(halfW, halfH, bufferWidth, bufferHeight), + bottomRight); + + Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); + } + + std::unique_ptr<ScreenCapture> screenshot() { + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + return screenshot; + } + + void asTransaction(const std::function<void(Transaction&)>& exec) { + Transaction t; + exec(t); + t.apply(true); + } + + static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) { + static BufferGenerator bufferGenerator; + return bufferGenerator.get(outBuffer, outFence); + } + + sp<SurfaceComposerClient> mClient; + + sp<IBinder> mDisplay; + uint32_t mDisplayWidth; + uint32_t mDisplayHeight; + uint32_t mDisplayLayerStack; + Rect mDisplayRect = Rect::INVALID_RECT; + + // leave room for ~256 layers + const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256; + + sp<SurfaceControl> mBlackBgSurface; + bool mColorManagementUsed; + +private: + void SetUpDisplay() { + mDisplay = mClient->getInternalDisplayToken(); + ASSERT_FALSE(mDisplay == nullptr) << "failed to get display"; + + // get display width/height + DisplayInfo info; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info)); + mDisplayWidth = info.w; + mDisplayHeight = info.h; + mDisplayRect = + Rect(static_cast<int32_t>(mDisplayWidth), static_cast<int32_t>(mDisplayHeight)); + + // After a new buffer is queued, SurfaceFlinger is notified and will + // latch the new buffer on next vsync. Let's heuristically wait for 3 + // vsyncs. + mBufferPostDelay = int32_t(1e6 / info.fps) * 3; + + mDisplayLayerStack = 0; + + mBlackBgSurface = + createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor); + + // set layer stack (b/68888219) + Transaction t; + t.setDisplayLayerStack(mDisplay, mDisplayLayerStack); + t.setCrop_legacy(mBlackBgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)); + t.setLayerStack(mBlackBgSurface, mDisplayLayerStack); + t.setColor(mBlackBgSurface, half3{0, 0, 0}); + t.setLayer(mBlackBgSurface, mLayerZBase); + t.apply(); + } + + void waitForLayerBuffers() { + // Request an empty transaction to get applied synchronously to ensure the buffer is + // latched. + Transaction().apply(true); + usleep(mBufferPostDelay); + } + + int32_t mBufferPostDelay; + + friend class LayerRenderPathTestHarness; +}; +} // namespace android + +#endif diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp new file mode 100644 index 0000000000..35c51e1915 --- /dev/null +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <private/android_filesystem_config.h> +#include <thread> +#include "LayerTransactionTest.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + + sp<ISurfaceComposer> composer = ComposerService::getComposerService(); + sp<GraphicBuffer> outBuffer; + Transaction() + .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) + .apply(true); + ASSERT_EQ(PERMISSION_DENIED, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); + + UIDFaker f(AID_SYSTEM); + + // By default the system can capture screenshots with secure layers but they + // will be blacked out + ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); + + { + SCOPED_TRACE("as system"); + auto shot = screenshot(); + shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } + + // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able + // to receive them...we are expected to take care with the results. + bool outCapturedSecureLayers; + ASSERT_EQ(NO_ERROR, + composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers, + ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0, + 0, false, ISurfaceComposer::eRotateNone, true)); + ASSERT_EQ(true, outCapturedSecureLayers); + ScreenCapture sc(outBuffer); + sc.expectColor(Rect(0, 0, 32, 32), Color::RED); +} + +TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + Transaction().setTransformToDisplayInverse(layer, false).apply(); + + ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32)); + + Transaction().setTransformToDisplayInverse(layer, true).apply(); +} + +TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE( + layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); + + // verify this doesn't cause a crash + Transaction().setSidebandStream(layer, nullptr).apply(); +} + +TEST_F(LayerTransactionTest, ReparentToSelf) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); + Transaction().reparent(layer, layer->getHandle()).apply(); + + { + // We expect the transaction to be silently dropped, but for SurfaceFlinger + // to still be functioning. + SCOPED_TRACE("after reparent to self"); + const Rect rect(0, 0, 32, 32); + auto shot = screenshot(); + shot->expectColor(rect, Color::RED); + shot->expectBorder(rect, Color::BLACK); + } +} + +// This test ensures that when we drop an app buffer in SurfaceFlinger, we merge +// the dropped buffer's damage region into the next buffer's damage region. If +// we don't do this, we'll report an incorrect damage region to hardware +// composer, resulting in broken rendering. This test checks the BufferQueue +// case. +// +// Unfortunately, we don't currently have a way to inspect the damage region +// SurfaceFlinger sends to hardware composer from a test, so this test requires +// the dev to manually watch the device's screen during the test to spot broken +// rendering. Because the results can't be automatically verified, this test is +// marked disabled. +TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDroppingBuffers) { + const int width = mDisplayWidth; + const int height = mDisplayHeight; + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height)); + const auto producer = layer->getIGraphicBufferProducer(); + const sp<IProducerListener> dummyListener(new DummyProducerListener); + IGraphicBufferProducer::QueueBufferOutput queueBufferOutput; + ASSERT_EQ(OK, + producer->connect(dummyListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput)); + + std::map<int, sp<GraphicBuffer>> slotMap; + auto slotToBuffer = [&](int slot, sp<GraphicBuffer>* buf) { + ASSERT_NE(nullptr, buf); + const auto iter = slotMap.find(slot); + ASSERT_NE(slotMap.end(), iter); + *buf = iter->second; + }; + + auto dequeue = [&](int* outSlot) { + ASSERT_NE(nullptr, outSlot); + *outSlot = -1; + int slot; + sp<Fence> fence; + uint64_t age; + FrameEventHistoryDelta timestamps; + const status_t dequeueResult = + producer->dequeueBuffer(&slot, &fence, width, height, PIXEL_FORMAT_RGBA_8888, + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, + &age, ×tamps); + if (dequeueResult == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { + sp<GraphicBuffer> newBuf; + ASSERT_EQ(OK, producer->requestBuffer(slot, &newBuf)); + ASSERT_NE(nullptr, newBuf.get()); + slotMap[slot] = newBuf; + } else { + ASSERT_EQ(OK, dequeueResult); + } + *outSlot = slot; + }; + + auto queue = [&](int slot, const Region& damage, nsecs_t displayTime) { + IGraphicBufferProducer::QueueBufferInput input( + /*timestamp=*/displayTime, /*isAutoTimestamp=*/false, HAL_DATASPACE_UNKNOWN, + /*crop=*/Rect::EMPTY_RECT, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, + /*transform=*/0, Fence::NO_FENCE); + input.setSurfaceDamage(damage); + IGraphicBufferProducer::QueueBufferOutput output; + ASSERT_EQ(OK, producer->queueBuffer(slot, input, &output)); + }; + + auto fillAndPostBuffers = [&](const Color& color) { + int slot1; + ASSERT_NO_FATAL_FAILURE(dequeue(&slot1)); + int slot2; + ASSERT_NO_FATAL_FAILURE(dequeue(&slot2)); + + sp<GraphicBuffer> buf1; + ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot1, &buf1)); + sp<GraphicBuffer> buf2; + ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot2, &buf2)); + TransactionUtils::fillGraphicBufferColor(buf1, Rect(width, height), color); + TransactionUtils::fillGraphicBufferColor(buf2, Rect(width, height), color); + + const auto displayTime = systemTime() + milliseconds_to_nanoseconds(100); + ASSERT_NO_FATAL_FAILURE(queue(slot1, Region::INVALID_REGION, displayTime)); + ASSERT_NO_FATAL_FAILURE( + queue(slot2, Region(Rect(width / 3, height / 3, 2 * width / 3, 2 * height / 3)), + displayTime)); + }; + + const auto startTime = systemTime(); + const std::array<Color, 3> colors = {Color::RED, Color::GREEN, Color::BLUE}; + int colorIndex = 0; + while (nanoseconds_to_seconds(systemTime() - startTime) < 10) { + ASSERT_NO_FATAL_FAILURE(fillAndPostBuffers(colors[colorIndex++ % colors.size()])); + std::this_thread::sleep_for(1s); + } + + ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU)); +} +} // namespace android diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp new file mode 100644 index 0000000000..daeff17ea3 --- /dev/null +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -0,0 +1,269 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/BufferItemConsumer.h> +#include "TransactionTestHarnesses.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +class LayerTypeAndRenderTypeTransactionTest + : public LayerTypeTransactionHarness, + public ::testing::WithParamInterface<std::tuple<uint32_t, RenderPath>> { +public: + LayerTypeAndRenderTypeTransactionTest() + : LayerTypeTransactionHarness(std::get<0>(GetParam())), + mRenderPathHarness(LayerRenderPathTestHarness(this, std::get<1>(GetParam()))) {} + + std::unique_ptr<ScreenCapture> getScreenCapture() { + return mRenderPathHarness.getScreenCapture(); + } + +protected: + LayerRenderPathTestHarness mRenderPathHarness; +}; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +INSTANTIATE_TEST_CASE_P( + LayerTypeAndRenderTypeTransactionTests, LayerTypeAndRenderTypeTransactionTest, + ::testing::Combine( + ::testing::Values( + static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue), + static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)), + ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT))); + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetSizeInvalid) { + // cannot test robustness against invalid sizes (zero or really huge) +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZBasic) { + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); + + Transaction().setLayer(layerR, mLayerZBase + 1).apply(); + { + SCOPED_TRACE("layerR"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + Transaction().setLayer(layerG, mLayerZBase + 2).apply(); + { + SCOPED_TRACE("layerG"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::GREEN); + } +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetRelativeZBug64572777) { + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); + + Transaction() + .setPosition(layerG, 16, 16) + .setRelativeLayer(layerG, layerR->getHandle(), 1) + .apply(); + + layerG.clear(); + // layerG should have been removed + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsHidden) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply(); + { + SCOPED_TRACE("layer hidden"); + getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); + } + + Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply(); + { + SCOPED_TRACE("layer shown"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsOpaque) { + const Color translucentRed = {100, 0, 0, 100}; + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); + + Transaction() + .setLayer(layerR, mLayerZBase + 1) + .setFlags(layerR, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque) + .apply(); + { + SCOPED_TRACE("layerR opaque"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, 0, 0, 255}); + } + + Transaction().setFlags(layerR, 0, layer_state_t::eLayerOpaque).apply(); + { + SCOPED_TRACE("layerR translucent"); + const uint8_t g = uint8_t(255 - translucentRed.a); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, g, 0, 255}); + } +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZNegative) { + sp<SurfaceControl> parent = + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceContainer); + Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply(); + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); + + Transaction() + .reparent(layerR, parent->getHandle()) + .reparent(layerG, parent->getHandle()) + .apply(); + Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); + { + SCOPED_TRACE("layerR"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::RED); + } + + Transaction().setLayer(layerR, -3).apply(); + { + SCOPED_TRACE("layerG"); + auto shot = getScreenCapture(); + shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN); + } +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetAlphaClamped) { + const Color color = {64, 0, 0, 255}; + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32)); + + Transaction().setAlpha(layer, 2.0f).apply(); + { + SCOPED_TRACE("clamped to 1.0f"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), color); + } + + Transaction().setAlpha(layer, -1.0f).apply(); + { + SCOPED_TRACE("clamped to 0.0f"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); + } +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { + sp<SurfaceControl> layer; + const uint8_t size = 64; + const uint8_t testArea = 4; + const float cornerRadius = 20.0f; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); + + Transaction() + .setCornerRadius(layer, cornerRadius) + .setCrop_legacy(layer, Rect(0, 0, size, size)) + .apply(); + { + const uint8_t bottom = size - 1; + const uint8_t right = size - 1; + auto shot = getScreenCapture(); + // Transparent corners + shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK); + shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::BLACK); + shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK); + shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::BLACK); + } +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { + sp<SurfaceControl> parent; + sp<SurfaceControl> child; + const uint8_t size = 64; + const uint8_t testArea = 4; + const float cornerRadius = 20.0f; + ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", size, size)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, size, size)); + ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); + + Transaction() + .setCornerRadius(parent, cornerRadius) + .setCrop_legacy(parent, Rect(0, 0, size, size)) + .reparent(child, parent->getHandle()) + .setPosition(child, 0, size / 2) + .apply(); + { + const uint8_t bottom = size - 1; + const uint8_t right = size - 1; + auto shot = getScreenCapture(); + // Top edge of child should not have rounded corners because it's translated in the parent + shot->expectColor(Rect(0, size / 2, right, static_cast<int>(bottom - cornerRadius)), + Color::GREEN); + // But bottom edges should have been clipped according to parent bounds + shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK); + shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK); + } +} +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) { + sp<SurfaceControl> bufferLayer; + ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32)); + + // color is ignored + Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply(); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); +} + +TEST_P(LayerTypeAndRenderTypeTransactionTest, SetLayerStackBasic) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + + Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply(); + { + SCOPED_TRACE("non-existing layer stack"); + getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); + } + + Transaction().setLayerStack(layer, mDisplayLayerStack).apply(); + { + SCOPED_TRACE("original layer stack"); + getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); + } +} +} // namespace android diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp new file mode 100644 index 0000000000..42ec34a129 --- /dev/null +++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <gui/BufferItemConsumer.h> +#include "TransactionTestHarnesses.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +class LayerTypeTransactionTest : public LayerTypeTransactionHarness, + public ::testing::WithParamInterface<uint32_t> { +public: + LayerTypeTransactionTest() : LayerTypeTransactionHarness(GetParam()) {} +}; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +INSTANTIATE_TEST_CASE_P( + LayerTypeTransactionTests, LayerTypeTransactionTest, + ::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue), + static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState))); + +TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { + sp<SurfaceControl> parent = + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceContainer); + Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply(); + sp<SurfaceControl> layerR; + sp<SurfaceControl> layerG; + sp<SurfaceControl> layerB; + ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); + ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); + + Transaction().reparent(layerB, parent->getHandle()).apply(); + + // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 + Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); + + std::unique_ptr<ScreenCapture> screenshot; + // only layerB is in this range + sp<IBinder> parentHandle = parent->getHandle(); + ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32)); + screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); +} + +TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) { + sp<SurfaceControl> parent = + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor); + + sp<SurfaceControl> childLayer; + ASSERT_NO_FATAL_FAILURE( + childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor, + parent.get())); + Transaction() + .setColor(childLayer, half3{1.0f, 0.0f, 0.0f}) + .setColor(parent, half3{0.0f, 0.0f, 0.0f}) + .show(childLayer) + .show(parent) + .setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)) + .setCrop_legacy(childLayer, Rect(0, 0, 20, 30)) + .apply(); + + Transaction() + .setRelativeLayer(childLayer, parent->getHandle(), -1) + .setLayer(childLayer, 1) + .apply(); + + { + SCOPED_TRACE("setLayer above"); + // Set layer should get applied and place the child above. + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED); + } + + Transaction() + .setLayer(childLayer, 1) + .setRelativeLayer(childLayer, parent->getHandle(), -1) + .apply(); + + { + SCOPED_TRACE("setRelative below"); + // Set relative layer should get applied and place the child below. + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK); + } +} + +TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) { + sp<SurfaceControl> parent = + LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor); + sp<SurfaceControl> relativeParent = + LayerTransactionTest::createLayer("RelativeParent", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor); + + sp<SurfaceControl> childLayer; + ASSERT_NO_FATAL_FAILURE( + childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */, + 0 /* buffer height */, + ISurfaceComposerClient::eFXSurfaceColor, + parent.get())); + Transaction() + .setColor(childLayer, half3{1.0f, 0.0f, 0.0f}) + .setColor(parent, half3{0.0f, 0.0f, 0.0f}) + .setColor(relativeParent, half3{0.0f, 1.0f, 0.0f}) + .show(childLayer) + .show(parent) + .show(relativeParent) + .setLayer(parent, mLayerZBase - 1) + .setLayer(relativeParent, mLayerZBase) + .apply(); + + Transaction().setRelativeLayer(childLayer, relativeParent->getHandle(), 1).apply(); + + { + SCOPED_TRACE("setLayer above"); + // Set layer should get applied and place the child above. + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED); + } + + Transaction().hide(relativeParent).apply(); + + { + SCOPED_TRACE("hide relative parent"); + // The relative should no longer be visible. + std::unique_ptr<ScreenCapture> screenshot; + ScreenCapture::captureScreen(&screenshot); + screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK); + } +} + +TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); + + sp<ISurfaceComposer> composer = ComposerService::getComposerService(); + sp<GraphicBuffer> outBuffer; + Transaction() + .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) + .apply(true); + ASSERT_EQ(PERMISSION_DENIED, + composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); + + Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); + ASSERT_EQ(NO_ERROR, composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); +} +TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) { + sp<SurfaceControl> layer; + ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); + + sp<IBinder> handle = layer->getHandle(); + ASSERT_TRUE(handle != nullptr); + + FrameStats frameStats; + mClient->getLayerFrameStats(handle, &frameStats); + + ASSERT_GT(frameStats.refreshPeriodNano, static_cast<nsecs_t>(0)); +} + +} // namespace android diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp new file mode 100644 index 0000000000..73f563dfc7 --- /dev/null +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -0,0 +1,1655 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class LayerUpdateTest : public LayerTransactionTest { +protected: + virtual void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + const auto display = SurfaceComposerClient::getInternalDisplayToken(); + ASSERT_FALSE(display == nullptr); + + DisplayInfo info; + ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info)); + + ssize_t displayWidth = info.w; + ssize_t displayHeight = info.h; + + // Background surface + mBGSurfaceControl = createLayer(String8("BG Test Surface"), displayWidth, displayHeight, 0); + ASSERT_TRUE(mBGSurfaceControl != nullptr); + ASSERT_TRUE(mBGSurfaceControl->isValid()); + TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195); + + // Foreground surface + mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0); + + ASSERT_TRUE(mFGSurfaceControl != nullptr); + ASSERT_TRUE(mFGSurfaceControl->isValid()); + + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); + + // Synchronization surface + mSyncSurfaceControl = createLayer(String8("Sync Test Surface"), 1, 1, 0); + ASSERT_TRUE(mSyncSurfaceControl != nullptr); + ASSERT_TRUE(mSyncSurfaceControl->isValid()); + + TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); + + asTransaction([&](Transaction& t) { + t.setDisplayLayerStack(display, 0); + + t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl); + + t.setLayer(mFGSurfaceControl, INT32_MAX - 1) + .setPosition(mFGSurfaceControl, 64, 64) + .show(mFGSurfaceControl); + + t.setLayer(mSyncSurfaceControl, INT32_MAX - 1) + .setPosition(mSyncSurfaceControl, displayWidth - 2, displayHeight - 2) + .show(mSyncSurfaceControl); + }); + } + + virtual void TearDown() { + LayerTransactionTest::TearDown(); + mBGSurfaceControl = 0; + mFGSurfaceControl = 0; + mSyncSurfaceControl = 0; + } + + void waitForPostedBuffers() { + // Since the sync surface is in synchronous mode (i.e. double buffered) + // posting three buffers to it should ensure that at least two + // SurfaceFlinger::handlePageFlip calls have been made, which should + // guaranteed that a buffer posted to another Surface has been retired. + TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); + TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); + TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); + } + + sp<SurfaceControl> mBGSurfaceControl; + sp<SurfaceControl> mFGSurfaceControl; + + // This surface is used to ensure that the buffers posted to + // mFGSurfaceControl have been picked up by SurfaceFlinger. + sp<SurfaceControl> mSyncSurfaceControl; +}; + +TEST_F(LayerUpdateTest, RelativesAreNotDetached) { + std::unique_ptr<ScreenCapture> sc; + + sp<SurfaceControl> relative = createLayer(String8("relativeTestSurface"), 10, 10, 0); + TransactionUtils::fillSurfaceRGBA8(relative, 10, 10, 10); + waitForPostedBuffers(); + + Transaction{} + .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1) + .setPosition(relative, 64, 64) + .apply(); + + { + // The relative should be on top of the FG control. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(64, 64, 10, 10, 10); + } + Transaction{}.detachChildren(mFGSurfaceControl).apply(); + + { + // Nothing should change at this point. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(64, 64, 10, 10, 10); + } + + Transaction{}.hide(relative).apply(); + + { + // Ensure that the relative was actually hidden, rather than + // being left in the detached but visible state. + ScreenCapture::captureScreen(&sc); + sc->expectFGColor(64, 64); + } +} + +class GeometryLatchingTest : public LayerUpdateTest { +protected: + void EXPECT_INITIAL_STATE(const char* trace) { + SCOPED_TRACE(trace); + ScreenCapture::captureScreen(&sc); + // We find the leading edge of the FG surface. + sc->expectFGColor(127, 127); + sc->expectBGColor(128, 128); + } + + void lockAndFillFGBuffer() { + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false); + } + + void unlockFGBuffer() { + sp<Surface> s = mFGSurfaceControl->getSurface(); + ASSERT_EQ(NO_ERROR, s->unlockAndPost()); + waitForPostedBuffers(); + } + + void completeFGResize() { + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); + waitForPostedBuffers(); + } + void restoreInitialState() { + asTransaction([&](Transaction& t) { + t.setSize(mFGSurfaceControl, 64, 64); + t.setPosition(mFGSurfaceControl, 64, 64); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); + }); + + EXPECT_INITIAL_STATE("After restoring initial state"); + } + std::unique_ptr<ScreenCapture> sc; +}; + +class CropLatchingTest : public GeometryLatchingTest { +protected: + void EXPECT_CROPPED_STATE(const char* trace) { + SCOPED_TRACE(trace); + ScreenCapture::captureScreen(&sc); + // The edge should be moved back one pixel by our crop. + sc->expectFGColor(126, 126); + sc->expectBGColor(127, 127); + sc->expectBGColor(128, 128); + } + + void EXPECT_RESIZE_STATE(const char* trace) { + SCOPED_TRACE(trace); + ScreenCapture::captureScreen(&sc); + // The FG is now resized too 128,128 at 64,64 + sc->expectFGColor(64, 64); + sc->expectFGColor(191, 191); + sc->expectBGColor(192, 192); + } +}; + +TEST_F(LayerUpdateTest, DeferredTransactionTest) { + std::unique_ptr<ScreenCapture> sc; + { + SCOPED_TRACE("before anything"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(32, 32); + sc->expectFGColor(96, 96); + sc->expectBGColor(160, 160); + } + + // set up two deferred transactions on different frames + asTransaction([&](Transaction& t) { + t.setAlpha(mFGSurfaceControl, 0.75); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber()); + }); + + asTransaction([&](Transaction& t) { + t.setPosition(mFGSurfaceControl, 128, 128); + t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), + mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); + }); + + { + SCOPED_TRACE("before any trigger"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(32, 32); + sc->expectFGColor(96, 96); + sc->expectBGColor(160, 160); + } + + // should trigger the first deferred transaction, but not the second one + TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); + { + SCOPED_TRACE("after first trigger"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(32, 32); + sc->checkPixel(96, 96, 162, 63, 96); + sc->expectBGColor(160, 160); + } + + // should show up immediately since it's not deferred + asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); }); + + // trigger the second deferred transaction + TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); + { + SCOPED_TRACE("after second trigger"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(32, 32); + sc->expectBGColor(96, 96); + sc->expectFGColor(160, 160); + } +} + +TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { + std::unique_ptr<ScreenCapture> sc; + + sp<SurfaceControl> childNoBuffer = + createSurface(mClient, "Bufferless child", 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20, + PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); + TransactionUtils::fillSurfaceRGBA8(childBuffer, 200, 200, 200); + SurfaceComposerClient::Transaction{} + .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10)) + .show(childNoBuffer) + .show(childBuffer) + .apply(true); + { + ScreenCapture::captureScreen(&sc); + sc->expectChildColor(73, 73); + sc->expectFGColor(74, 74); + } + SurfaceComposerClient::Transaction{} + .setCrop_legacy(childNoBuffer, Rect(0, 0, 20, 20)) + .apply(true); + { + ScreenCapture::captureScreen(&sc); + sc->expectChildColor(73, 73); + sc->expectChildColor(74, 74); + } +} + +TEST_F(LayerUpdateTest, MergingTransactions) { + std::unique_ptr<ScreenCapture> sc; + { + SCOPED_TRACE("before move"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(0, 12); + sc->expectFGColor(75, 75); + sc->expectBGColor(145, 145); + } + + Transaction t1, t2; + t1.setPosition(mFGSurfaceControl, 128, 128); + t2.setPosition(mFGSurfaceControl, 0, 0); + // We expect that the position update from t2 now + // overwrites the position update from t1. + t1.merge(std::move(t2)); + t1.apply(); + + { + ScreenCapture::captureScreen(&sc); + sc->expectFGColor(1, 1); + } +} + +TEST_F(LayerUpdateTest, MergingTransactionFlags) { + Transaction().hide(mFGSurfaceControl).apply(); + std::unique_ptr<ScreenCapture> sc; + { + SCOPED_TRACE("before merge"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(0, 12); + sc->expectBGColor(75, 75); + sc->expectBGColor(145, 145); + } + + Transaction t1, t2; + t1.show(mFGSurfaceControl); + t2.setFlags(mFGSurfaceControl, 0 /* flags */, layer_state_t::eLayerSecure /* mask */); + t1.merge(std::move(t2)); + t1.apply(); + + { + SCOPED_TRACE("after merge"); + ScreenCapture::captureScreen(&sc); + sc->expectFGColor(75, 75); + } +} + +class ChildLayerTest : public LayerUpdateTest { +protected: + void SetUp() override { + LayerUpdateTest::SetUp(); + mChild = createSurface(mClient, "Child surface", 10, 15, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); + + { + SCOPED_TRACE("before anything"); + mCapture = screenshot(); + mCapture->expectChildColor(64, 64); + } + } + void TearDown() override { + LayerUpdateTest::TearDown(); + mChild = 0; + } + + sp<SurfaceControl> mChild; + std::unique_ptr<ScreenCapture> mCapture; +}; + +TEST_F(ChildLayerTest, ChildLayerPositioning) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); }); + + { + mCapture = screenshot(); + // Top left of foreground should now be at 0, 0 + mCapture->expectFGColor(0, 0); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(10, 10); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(20, 20); + } +} + +TEST_F(ChildLayerTest, ChildLayerCropping) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); + }); + + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(4, 4); + mCapture->expectBGColor(5, 5); + } +} + +TEST_F(ChildLayerTest, ChildLayerConstraints) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setPosition(mChild, 63, 63); + }); + + { + mCapture = screenshot(); + mCapture->expectFGColor(0, 0); + // Last pixel in foreground should now be the child. + mCapture->expectChildColor(63, 63); + // But the child should be constrained and the next pixel + // must be the background + mCapture->expectBGColor(64, 64); + } +} + +TEST_F(ChildLayerTest, ChildLayerScaling) { + asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); }); + + // Find the boundary between the parent and child + { + mCapture = screenshot(); + mCapture->expectChildColor(9, 9); + mCapture->expectFGColor(10, 10); + } + + asTransaction([&](Transaction& t) { t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); }); + + // The boundary should be twice as far from the origin now. + // The pixels from the last test should all be child now + { + mCapture = screenshot(); + mCapture->expectChildColor(9, 9); + mCapture->expectChildColor(10, 10); + mCapture->expectChildColor(19, 19); + mCapture->expectFGColor(20, 20); + } +} + +// A child with a scale transform should be cropped by its parent bounds. +TEST_F(ChildLayerTest, ChildLayerScalingCroppedByParent) { + asTransaction([&](Transaction& t) { + t.setPosition(mFGSurfaceControl, 0, 0); + t.setPosition(mChild, 0, 0); + }); + + // Find the boundary between the parent and child. + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 9); + mCapture->expectFGColor(10, 10); + } + + asTransaction([&](Transaction& t) { t.setMatrix(mChild, 10.0, 0, 0, 10.0); }); + + // The child should fill its parent bounds and be cropped by it. + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(63, 63); + mCapture->expectBGColor(64, 64); + } +} + +TEST_F(ChildLayerTest, ChildLayerAlpha) { + TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0); + TransactionUtils::fillSurfaceRGBA8(mChild, 0, 254, 0); + waitForPostedBuffers(); + + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); + + { + mCapture = screenshot(); + // Unblended child color + mCapture->checkPixel(0, 0, 0, 254, 0); + } + + asTransaction([&](Transaction& t) { t.setAlpha(mChild, 0.5); }); + + { + mCapture = screenshot(); + // Child and BG blended. + mCapture->checkPixel(0, 0, 127, 127, 0); + } + + asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.5); }); + + { + mCapture = screenshot(); + // Child and BG blended. + mCapture->checkPixel(0, 0, 95, 64, 95); + } +} + +TEST_F(ChildLayerTest, ReparentChildren) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + asTransaction([&](Transaction& t) { + t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle()); + }); + + { + mCapture = screenshot(); + mCapture->expectFGColor(64, 64); + // In reparenting we should have exposed the entire foreground surface. + mCapture->expectFGColor(74, 74); + // And the child layer should now begin at 10, 10 (since the BG + // layer is at (0, 0)). + mCapture->expectBGColor(9, 9); + mCapture->expectChildColor(10, 10); + } +} + +TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { + sp<SurfaceControl> mGrandChild = + createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111); + + { + SCOPED_TRACE("Grandchild visible"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } + + mChild.clear(); + + { + SCOPED_TRACE("After destroying child"); + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(64, 64); + } + + asTransaction([&](Transaction& t) { t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); }); + + { + SCOPED_TRACE("After reparenting grandchild"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 111, 111, 111); + } +} + +TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) { + sp<SurfaceControl> mGrandChild = + createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111); + + // draw grand child behind the foreground surface + asTransaction([&](Transaction& t) { + t.setRelativeLayer(mGrandChild, mFGSurfaceControl->getHandle(), -1); + }); + + { + SCOPED_TRACE("Child visible"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 200, 200, 200); + } + + asTransaction([&](Transaction& t) { + t.reparent(mChild, nullptr); + t.reparentChildren(mChild, mFGSurfaceControl->getHandle()); + }); + + { + SCOPED_TRACE("foreground visible reparenting grandchild"); + ScreenCapture::captureScreen(&mCapture); + mCapture->checkPixel(64, 64, 195, 63, 63); + } +} + +TEST_F(ChildLayerTest, DetachChildrenSameClient) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); }); + + asTransaction([&](Transaction& t) { t.hide(mChild); }); + + // Since the child has the same client as the parent, it will not get + // detached and will be hidden. + { + mCapture = screenshot(); + mCapture->expectFGColor(64, 64); + mCapture->expectFGColor(74, 74); + mCapture->expectFGColor(84, 84); + } +} + +TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { + sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient; + sp<SurfaceControl> mChildNewClient = + createSurface(mNewComposerClient, "New Child Test Surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + + ASSERT_TRUE(mChildNewClient->isValid()); + + TransactionUtils::fillSurfaceRGBA8(mChildNewClient, 200, 200, 200); + + asTransaction([&](Transaction& t) { + t.hide(mChild); + t.show(mChildNewClient); + t.setPosition(mChildNewClient, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); }); + + asTransaction([&](Transaction& t) { t.hide(mChildNewClient); }); + + // Nothing should have changed. + { + mCapture = screenshot(); + mCapture->expectFGColor(64, 64); + mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(84, 84); + } +} + +TEST_F(ChildLayerTest, DetachChildrenThenAttach) { + sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; + sp<SurfaceControl> childNewClient = + newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + + ASSERT_TRUE(childNewClient != nullptr); + ASSERT_TRUE(childNewClient->isValid()); + + TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200); + + Transaction() + .hide(mChild) + .show(childNewClient) + .setPosition(childNewClient, 10, 10) + .setPosition(mFGSurfaceControl, 64, 64) + .apply(); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + Transaction().detachChildren(mFGSurfaceControl).apply(); + Transaction().hide(childNewClient).apply(); + + // Nothing should have changed. + { + mCapture = screenshot(); + mCapture->expectFGColor(64, 64); + mCapture->expectChildColor(74, 74); + mCapture->expectFGColor(84, 84); + } + + sp<SurfaceControl> newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0); + fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32, + 32); + Transaction() + .setLayer(newParentSurface, INT32_MAX - 1) + .show(newParentSurface) + .setPosition(newParentSurface, 20, 20) + .reparent(childNewClient, newParentSurface->getHandle()) + .apply(); + { + mCapture = screenshot(); + // Child is now hidden. + mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED); + } +} +TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) { + sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; + sp<SurfaceControl> childNewClient = + newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + + ASSERT_TRUE(childNewClient != nullptr); + ASSERT_TRUE(childNewClient->isValid()); + + TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200); + + Transaction() + .hide(mChild) + .show(childNewClient) + .setPosition(childNewClient, 10, 10) + .setPosition(mFGSurfaceControl, 64, 64) + .apply(); + + { + mCapture = screenshot(); + Rect rect = Rect(74, 74, 84, 84); + mCapture->expectBorder(rect, Color{195, 63, 63, 255}); + mCapture->expectColor(rect, Color{200, 200, 200, 255}); + } + + Transaction() + .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()) + .apply(); + Transaction().detachChildren(mFGSurfaceControl).apply(); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32)); + + // BufferLayer can still dequeue buffers even though there's a detached layer with a + // deferred transaction. + { + SCOPED_TRACE("new buffer"); + mCapture = screenshot(); + Rect rect = Rect(74, 74, 84, 84); + mCapture->expectBorder(rect, Color::RED); + mCapture->expectColor(rect, Color{200, 200, 200, 255}); + } +} + +TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); + + { + mCapture = screenshot(); + // We've positioned the child in the top left. + mCapture->expectChildColor(0, 0); + // But it's only 10x15. + mCapture->expectFGColor(10, 15); + } + + asTransaction([&](Transaction& t) { + t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // We cause scaling by 2. + t.setSize(mFGSurfaceControl, 128, 128); + }); + + { + mCapture = screenshot(); + // We've positioned the child in the top left. + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(10, 10); + mCapture->expectChildColor(19, 29); + // And now it should be scaled all the way to 20x30 + mCapture->expectFGColor(20, 30); + } +} + +// Regression test for b/37673612 +TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); + + { + mCapture = screenshot(); + // We've positioned the child in the top left. + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 14); + // But it's only 10x15. + mCapture->expectFGColor(10, 15); + } + // We set things up as in b/37673612 so that there is a mismatch between the buffer size and + // the WM specified state size. + asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); }); + sp<Surface> s = mFGSurfaceControl->getSurface(); + auto anw = static_cast<ANativeWindow*>(s.get()); + native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); + native_window_set_buffers_dimensions(anw, 64, 128); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); + waitForPostedBuffers(); + + { + // The child should still be in the same place and not have any strange scaling as in + // b/37673612. + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectFGColor(10, 10); + } +} + +// A child with a buffer transform from its parents should be cropped by its parent bounds. +TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferTransform) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setSize(mChild, 100, 100); + }); + TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); + + { + mCapture = screenshot(); + + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(63, 63); + mCapture->expectBGColor(64, 64); + } + + asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); }); + sp<Surface> s = mFGSurfaceControl->getSurface(); + auto anw = static_cast<ANativeWindow*>(s.get()); + // Apply a 90 transform on the buffer. + native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); + native_window_set_buffers_dimensions(anw, 64, 128); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); + waitForPostedBuffers(); + + // The child should be cropped by the new parent bounds. + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(99, 63); + mCapture->expectFGColor(100, 63); + mCapture->expectBGColor(128, 64); + } +} + +// A child with a scale transform from its parents should be cropped by its parent bounds. +TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferScale) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + t.setSize(mChild, 200, 200); + }); + TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); + + { + mCapture = screenshot(); + + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(63, 63); + mCapture->expectBGColor(64, 64); + } + + asTransaction([&](Transaction& t) { + t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + // Set a scaling by 2. + t.setSize(mFGSurfaceControl, 128, 128); + }); + + // Child should inherit its parents scale but should be cropped by its parent bounds. + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(127, 127); + mCapture->expectBGColor(128, 128); + } +} + +// Regression test for b/127368943 +// Child should ignore the buffer transform but apply parent scale transform. +TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 0, 0); + t.setPosition(mFGSurfaceControl, 0, 0); + }); + + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 14); + mCapture->expectFGColor(10, 15); + } + + // Change the size of the foreground to 128 * 64 so we can test rotation as well. + asTransaction([&](Transaction& t) { + t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); + t.setSize(mFGSurfaceControl, 128, 64); + }); + sp<Surface> s = mFGSurfaceControl->getSurface(); + auto anw = static_cast<ANativeWindow*>(s.get()); + // Apply a 90 transform on the buffer and submit a buffer half the expected size so that we + // have an effective scale of 2.0 applied to the buffer along with a rotation transform. + native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); + native_window_set_buffers_dimensions(anw, 32, 64); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); + waitForPostedBuffers(); + + // The child should ignore the buffer transform but apply the 2.0 scale from parent. + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(19, 29); + mCapture->expectFGColor(20, 30); + } +} + +TEST_F(ChildLayerTest, Bug36858924) { + // Destroy the child layer + mChild.clear(); + + // Now recreate it as hidden + mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eHidden, mFGSurfaceControl.get()); + + // Show the child layer in a deferred transaction + asTransaction([&](Transaction& t) { + t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), + mFGSurfaceControl->getSurface()->getNextFrameNumber()); + t.show(mChild); + }); + + // Render the foreground surface a few times + // + // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third + // frame because SurfaceFlinger would never process the deferred transaction and would therefore + // never acquire/release the first buffer + ALOGI("Filling 1"); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); + ALOGI("Filling 2"); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255); + ALOGI("Filling 3"); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0); + ALOGI("Filling 4"); + TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); +} + +TEST_F(ChildLayerTest, Reparent) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); }); + + { + mCapture = screenshot(); + mCapture->expectFGColor(64, 64); + // In reparenting we should have exposed the entire foreground surface. + mCapture->expectFGColor(74, 74); + // And the child layer should now begin at 10, 10 (since the BG + // layer is at (0, 0)). + mCapture->expectBGColor(9, 9); + mCapture->expectChildColor(10, 10); + } +} + +TEST_F(ChildLayerTest, ReparentToNoParent) { + asTransaction([&](Transaction& t) { + t.show(mChild); + t.setPosition(mChild, 10, 10); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); }); + { + mCapture = screenshot(); + // The surface should now be offscreen. + mCapture->expectFGColor(64, 64); + mCapture->expectFGColor(74, 74); + mCapture->expectFGColor(84, 84); + } +} + +TEST_F(ChildLayerTest, ReparentFromNoParent) { + sp<SurfaceControl> newSurface = createLayer(String8("New Surface"), 10, 10, 0); + ASSERT_TRUE(newSurface != nullptr); + ASSERT_TRUE(newSurface->isValid()); + + TransactionUtils::fillSurfaceRGBA8(newSurface, 63, 195, 63); + asTransaction([&](Transaction& t) { + t.hide(mChild); + t.show(newSurface); + t.setPosition(newSurface, 10, 10); + t.setLayer(newSurface, INT32_MAX - 2); + t.setPosition(mFGSurfaceControl, 64, 64); + }); + + { + mCapture = screenshot(); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // At 10, 10 we should see the new surface + mCapture->checkPixel(10, 10, 63, 195, 63); + } + + asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); }); + + { + mCapture = screenshot(); + // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from + // mFGSurface, putting it at 74, 74. + mCapture->expectFGColor(64, 64); + mCapture->checkPixel(74, 74, 63, 195, 63); + mCapture->expectFGColor(84, 84); + } +} + +TEST_F(ChildLayerTest, NestedChildren) { + sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); + TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50); + + { + mCapture = screenshot(); + // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer + // which begins at 64, 64 + mCapture->checkPixel(64, 64, 50, 50, 50); + } +} + +TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { + sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 128, 128, 0); + TransactionUtils::fillSurfaceRGBA8(relative, 255, 255, 255); + + Transaction t; + t.setLayer(relative, INT32_MAX) + .setRelativeLayer(mChild, relative->getHandle(), 1) + .setPosition(mFGSurfaceControl, 0, 0) + .apply(true); + + // We expect that the child should have been elevated above our + // INT_MAX layer even though it's not a child of it. + { + mCapture = screenshot(); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 9); + mCapture->checkPixel(10, 10, 255, 255, 255); + } +} + +class BoundlessLayerTest : public LayerUpdateTest { +protected: + std::unique_ptr<ScreenCapture> mCapture; +}; + +// Verify setting a size on a buffer layer has no effect. +TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) { + sp<SurfaceControl> bufferLayer = + createSurface(mClient, "BufferLayer", 45, 45, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); + ASSERT_TRUE(bufferLayer->isValid()); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30)); + asTransaction([&](Transaction& t) { t.show(bufferLayer); }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 94, 94), Color::BLACK); + // Buffer layer should not extend past buffer bounds + mCapture->expectFGColor(95, 95); + } +} + +// Verify a boundless color layer will fill its parent bounds. The parent has a buffer size +// which will crop the color layer. +TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) { + sp<SurfaceControl> colorLayer = + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get()); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has +// a crop which will be used to crop the color layer. +TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) { + sp<SurfaceControl> cropLayer = createSurface(mClient, "CropLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); + ASSERT_TRUE(cropLayer->isValid()); + sp<SurfaceControl> colorLayer = + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get()); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10)); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(cropLayer); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // 5 pixels from the foreground we should see the child surface + mCapture->expectColor(Rect(69, 69, 74, 74), Color::BLACK); + // 10 pixels from the foreground we should be back to the foreground surface + mCapture->expectFGColor(74, 74); + } +} + +// Verify for boundless layer with no children, their transforms have no effect. +TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) { + sp<SurfaceControl> colorLayer = + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get()); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setPosition(colorLayer, 320, 320); + t.setMatrix(colorLayer, 2, 0, 0, 2); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify for boundless layer with children, their transforms have an effect. +TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) { + sp<SurfaceControl> boundlessLayerRightShift = + createSurface(mClient, "BoundlessLayerRightShift", 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); + ASSERT_TRUE(boundlessLayerRightShift->isValid()); + sp<SurfaceControl> boundlessLayerDownShift = + createSurface(mClient, "BoundlessLayerLeftShift", 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, boundlessLayerRightShift.get()); + ASSERT_TRUE(boundlessLayerDownShift->isValid()); + sp<SurfaceControl> colorLayer = + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, boundlessLayerDownShift.get()); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setPosition(boundlessLayerRightShift, 32, 0); + t.show(boundlessLayerRightShift); + t.setPosition(boundlessLayerDownShift, 0, 32); + t.show(boundlessLayerDownShift); + t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(96, 96, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify child layers do not get clipped if they temporarily move into the negative +// coordinate space as the result of an intermediate transformation. +TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) { + sp<SurfaceControl> boundlessLayer = + mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + 0 /* flags */, mFGSurfaceControl.get()); + ASSERT_TRUE(boundlessLayer != nullptr); + ASSERT_TRUE(boundlessLayer->isValid()); + sp<SurfaceControl> colorLayer = + mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, boundlessLayer.get()); + ASSERT_TRUE(colorLayer != nullptr); + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + // shift child layer off bounds. If this layer was not boundless, we will + // expect the child layer to be cropped. + t.setPosition(boundlessLayer, 32, 32); + t.show(boundlessLayer); + t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); + // undo shift by parent + t.setPosition(colorLayer, -32, -32); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(129, 129); + } +} + +// Verify for boundless root layers with children, their transforms have an effect. +TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) { + sp<SurfaceControl> rootBoundlessLayer = createSurface(mClient, "RootBoundlessLayer", 0, 0, + PIXEL_FORMAT_RGBA_8888, 0 /* flags */); + ASSERT_TRUE(rootBoundlessLayer->isValid()); + sp<SurfaceControl> colorLayer = + createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, + ISurfaceComposerClient::eFXSurfaceColor, rootBoundlessLayer.get()); + + ASSERT_TRUE(colorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setLayer(rootBoundlessLayer, INT32_MAX - 1); + t.setPosition(rootBoundlessLayer, 32, 32); + t.show(rootBoundlessLayer); + t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); + t.setColor(colorLayer, half3{0, 0, 0}); + t.show(colorLayer); + t.hide(mFGSurfaceControl); + }); + { + mCapture = screenshot(); + // Top left of background must now be visible + mCapture->expectBGColor(0, 0); + // Top left of foreground must now be visible + mCapture->expectBGColor(31, 31); + // Foreground Surface bounds must be color layer + mCapture->expectColor(Rect(32, 32, 96, 96), Color::BLACK); + // Color layer should not extend past foreground bounds + mCapture->expectBGColor(97, 97); + } +} + +class ScreenCaptureTest : public LayerUpdateTest { +protected: + std::unique_ptr<ScreenCapture> mCapture; +}; + +TEST_F(ScreenCaptureTest, CaptureSingleLayer) { + auto bgHandle = mBGSurfaceControl->getHandle(); + ScreenCapture::captureLayers(&mCapture, bgHandle); + mCapture->expectBGColor(0, 0); + // Doesn't capture FG layer which is at 64, 64 + mCapture->expectBGColor(64, 64); +} + +TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + // Captures mFGSurfaceControl layer and its child. + ScreenCapture::captureLayers(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + // Captures mFGSurfaceControl's child + ScreenCapture::captureChildLayers(&mCapture, fgHandle); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->expectChildColor(0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureLayerExclude) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200); + + SurfaceComposerClient::Transaction() + .show(child) + .show(child2) + .setLayer(child, 1) + .setLayer(child2, 2) + .apply(true); + + // Child2 would be visible but its excluded, so we should see child1 color instead. + ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()}); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->checkPixel(0, 0, 200, 200, 200); +} + +// Like the last test but verifies that children are also exclude. +TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200); + sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, child2.get()); + TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200); + + SurfaceComposerClient::Transaction() + .show(child) + .show(child2) + .show(child3) + .setLayer(child, 1) + .setLayer(child2, 2) + .apply(true); + + // Child2 would be visible but its excluded, so we should see child1 color instead. + ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()}); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->checkPixel(0, 0, 200, 200, 200); +} + +TEST_F(ScreenCaptureTest, CaptureTransparent) { + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(child).apply(true); + + auto childHandle = child->getHandle(); + + // Captures child + ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20}); + mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255}); + // Area outside of child's bounds is transparent. + mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); +} + +TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + ASSERT_NE(nullptr, child.get()) << "failed to create surface"; + sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100); + + SurfaceComposerClient::Transaction() + .show(child) + // Set relative layer above fg layer so should be shown above when computing all layers. + .setRelativeLayer(relative, fgHandle, 1) + .show(relative) + .apply(true); + + // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured. + ScreenCapture::captureLayers(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100); + + SurfaceComposerClient::Transaction() + .show(child) + // Set relative layer below fg layer but relative to child layer so it should be shown + // above child layer. + .setLayer(relative, -1) + .setRelativeLayer(relative, child->getHandle(), 1) + .show(relative) + .apply(true); + + // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its + // relative value should be taken into account, placing it above child layer. + ScreenCapture::captureLayers(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + // Relative layer is showing on top of child layer + mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255}); +} + +// In the following tests we verify successful skipping of a parent layer, +// so we use the same verification logic and only change how we mutate +// the parent layer to verify that various properties are ignored. +class ScreenCaptureChildOnlyTest : public LayerUpdateTest { +public: + void SetUp() override { + LayerUpdateTest::SetUp(); + + mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, + mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); + + SurfaceComposerClient::Transaction().show(mChild).apply(true); + } + + void verify(std::function<void()> verifyStartingState) { + // Verify starting state before a screenshot is taken. + verifyStartingState(); + + // Verify child layer does not inherit any of the properties of its + // parent when its screenshot is captured. + auto fgHandle = mFGSurfaceControl->getHandle(); + ScreenCapture::captureChildLayers(&mCapture, fgHandle); + mCapture->checkPixel(10, 10, 0, 0, 0); + mCapture->expectChildColor(0, 0); + + // Verify all assumptions are still true after the screenshot is taken. + verifyStartingState(); + } + + std::unique_ptr<ScreenCapture> mCapture; + sp<SurfaceControl> mChild; +}; + +// Regression test b/76099859 +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { + SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true); + + // Even though the parent is hidden we should still capture the child. + + // Before and after reparenting, verify child is properly hidden + // when rendering full-screen. + verify([&] { screenshot()->expectBGColor(64, 64); }); +} + +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { + SurfaceComposerClient::Transaction() + .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1)) + .apply(true); + + // Even though the parent is cropped out we should still capture the child. + + // Before and after reparenting, verify child is cropped by parent. + verify([&] { screenshot()->expectBGColor(65, 65); }); +} + +// Regression test b/124372894 +TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) { + SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true); + + // We should not inherit the parent scaling. + + // Before and after reparenting, verify child is properly scaled. + verify([&] { screenshot()->expectChildColor(80, 80); }); +} + +TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { + auto fgHandle = mFGSurfaceControl->getHandle(); + + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + + sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); + + TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50); + SurfaceComposerClient::Transaction() + .show(child) + .setPosition(grandchild, 5, 5) + .show(grandchild) + .apply(true); + + // Captures mFGSurfaceControl, its child, and the grandchild. + ScreenCapture::captureLayers(&mCapture, fgHandle); + mCapture->expectFGColor(10, 10); + mCapture->expectChildColor(0, 0); + mCapture->checkPixel(5, 5, 50, 50, 50); +} + +TEST_F(ScreenCaptureTest, CaptureChildOnly) { + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + auto childHandle = child->getHandle(); + + SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); + + // Captures only the child layer, and not the parent. + ScreenCapture::captureLayers(&mCapture, childHandle); + mCapture->expectChildColor(0, 0); + mCapture->expectChildColor(9, 9); +} + +TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { + sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, + PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); + TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); + auto childHandle = child->getHandle(); + + sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5, + PIXEL_FORMAT_RGBA_8888, 0, child.get()); + TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50); + + SurfaceComposerClient::Transaction() + .show(child) + .setPosition(grandchild, 5, 5) + .show(grandchild) + .apply(true); + + auto grandchildHandle = grandchild->getHandle(); + + // Captures only the grandchild. + ScreenCapture::captureLayers(&mCapture, grandchildHandle); + mCapture->checkPixel(0, 0, 50, 50, 50); + mCapture->checkPixel(4, 4, 50, 50, 50); +} + +TEST_F(ScreenCaptureTest, CaptureCrop) { + sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); + sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30, + PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + + const Rect crop = Rect(0, 0, 30, 30); + ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); + // Capturing the cropped screen, cropping out the shown red area, should leave only the blue + // area visible. + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureSize) { + sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); + sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30, + PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); + + SurfaceComposerClient::Transaction() + .setLayer(redLayer, INT32_MAX - 1) + .show(redLayer) + .show(blueLayer) + .apply(true); + + auto redLayerHandle = redLayer->getHandle(); + + // Capturing full screen should have both red and blue are visible. + ScreenCapture::captureLayers(&mCapture, redLayerHandle); + mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); + + ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); + // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. + mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); + // red area below the blue area + mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); + // red area to the right of the blue area + mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); + mCapture->checkPixel(30, 30, 0, 0, 0); +} + +TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { + sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); + + ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); + + auto redLayerHandle = redLayer->getHandle(); + redLayer.clear(); + SurfaceComposerClient::Transaction().apply(true); + + sp<GraphicBuffer> outBuffer; + + // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND + sp<ISurfaceComposer> sf(ComposerService::getComposerService()); + ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); +} +} // namespace android diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp new file mode 100644 index 0000000000..066c9aa3ce --- /dev/null +++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class MultiDisplayLayerBoundsTest : public LayerTransactionTest { +protected: + virtual void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + mMainDisplay = SurfaceComposerClient::getInternalDisplayToken(); + SurfaceComposerClient::getDisplayInfo(mMainDisplay, &mMainDisplayInfo); + + sp<IGraphicBufferConsumer> consumer; + BufferQueue::createBufferQueue(&mProducer, &consumer); + consumer->setConsumerName(String8("Virtual disp consumer")); + consumer->setDefaultBufferSize(mMainDisplayInfo.w, mMainDisplayInfo.h); + } + + virtual void TearDown() { + SurfaceComposerClient::destroyDisplay(mVirtualDisplay); + LayerTransactionTest::TearDown(); + mColorLayer = 0; + } + + void createDisplay(const Rect& layerStackRect, uint32_t layerStack) { + mVirtualDisplay = + SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/); + asTransaction([&](Transaction& t) { + t.setDisplaySurface(mVirtualDisplay, mProducer); + t.setDisplayLayerStack(mVirtualDisplay, layerStack); + t.setDisplayProjection(mVirtualDisplay, mMainDisplayInfo.orientation, layerStackRect, + Rect(mMainDisplayInfo.w, mMainDisplayInfo.h)); + }); + } + + void createColorLayer(uint32_t layerStack) { + mColorLayer = + createSurface(mClient, "ColorLayer", 0 /* buffer width */, 0 /* buffer height */, + PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor); + ASSERT_TRUE(mColorLayer != nullptr); + ASSERT_TRUE(mColorLayer->isValid()); + asTransaction([&](Transaction& t) { + t.setLayerStack(mColorLayer, layerStack); + t.setCrop_legacy(mColorLayer, Rect(0, 0, 30, 40)); + t.setLayer(mColorLayer, INT32_MAX - 2); + t.setColor(mColorLayer, + half3{mExpectedColor.r / 255.0f, mExpectedColor.g / 255.0f, + mExpectedColor.b / 255.0f}); + t.show(mColorLayer); + }); + } + + DisplayInfo mMainDisplayInfo; + sp<IBinder> mMainDisplay; + sp<IBinder> mVirtualDisplay; + sp<IGraphicBufferProducer> mProducer; + sp<SurfaceControl> mColorLayer; + Color mExpectedColor = {63, 63, 195, 255}; +}; + +TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInVirtualDisplay) { + createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 1 /* layerStack */); + createColorLayer(1 /* layerStack */); + + asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); }); + + // Verify color layer does not render on main display. + std::unique_ptr<ScreenCapture> sc; + ScreenCapture::captureScreen(&sc, mMainDisplay); + sc->expectColor(Rect(10, 10, 40, 50), {0, 0, 0, 255}); + sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); + + // Verify color layer renders correctly on virtual display. + ScreenCapture::captureScreen(&sc, mVirtualDisplay); + sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor); + sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 0}); +} + +TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) { + // Create a display and set its layer stack to the main display's layer stack so + // the contents of the main display are mirrored on to the virtual display. + + // Assumption here is that the new mirrored display has the same viewport as the + // primary display that it is mirroring. + createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 0 /* layerStack */); + createColorLayer(0 /* layerStack */); + + asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); }); + + // Verify color layer renders correctly on main display and it is mirrored on the + // virtual display. + std::unique_ptr<ScreenCapture> sc; + ScreenCapture::captureScreen(&sc, mMainDisplay); + sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor); + sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); + + ScreenCapture::captureScreen(&sc, mVirtualDisplay); + sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor); + sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); +} + +} // namespace android diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp new file mode 100644 index 0000000000..8549db2e0b --- /dev/null +++ b/services/surfaceflinger/tests/RelativeZ_test.cpp @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerTransactionTest.h" + +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +::testing::Environment* const binderEnv = + ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); + +class RelativeZTest : public LayerTransactionTest { +protected: + virtual void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + const auto display = SurfaceComposerClient::getInternalDisplayToken(); + ASSERT_FALSE(display == nullptr); + + // Back layer + mBackgroundLayer = createColorLayer("Background layer", Color::RED); + + // Front layer + mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN); + + asTransaction([&](Transaction& t) { + t.setDisplayLayerStack(display, 0); + t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer); + t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer); + }); + } + + virtual void TearDown() { + LayerTransactionTest::TearDown(); + mBackgroundLayer = 0; + mForegroundLayer = 0; + } + + sp<SurfaceControl> mBackgroundLayer; + sp<SurfaceControl> mForegroundLayer; +}; + +// When a layer is reparented offscreen, remove relative z order if the relative parent +// is still onscreen so that the layer is not drawn. +TEST_F(RelativeZTest, LayerRemoved) { + std::unique_ptr<ScreenCapture> sc; + + // Background layer (RED) + // Child layer (WHITE) (relative to foregroud layer) + // Foregroud layer (GREEN) + sp<SurfaceControl> childLayer = + createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get()); + + Transaction{} + .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1) + .show(childLayer) + .apply(); + + { + // The childLayer should be in front of the FG control. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); + } + + // Background layer (RED) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLayer, nullptr).apply(); + + // Background layer (RED) + // Child layer (WHITE) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply(); + + { + // The relative z info for child layer should be reset, leaving FG control on top. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } +} + +// When a layer is reparented offscreen, preseve relative z order if the relative parent +// is also offscreen. Regression test b/132613412 +TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) { + std::unique_ptr<ScreenCapture> sc; + + // Background layer (RED) + // Foregroud layer (GREEN) + // child level 1 (WHITE) + // child level 2a (BLUE) + // child level 3 (GREEN) (relative to child level 2b) + // child level 2b (BLACK) + sp<SurfaceControl> childLevel1 = + createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get()); + sp<SurfaceControl> childLevel2a = + createColorLayer("child level 2a", Color::BLUE, childLevel1.get()); + sp<SurfaceControl> childLevel2b = + createColorLayer("child level 2b", Color::BLACK, childLevel1.get()); + sp<SurfaceControl> childLevel3 = + createColorLayer("child level 3", Color::GREEN, childLevel2a.get()); + + Transaction{} + .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1) + .show(childLevel2a) + .show(childLevel2b) + .show(childLevel3) + .apply(); + + { + // The childLevel3 should be in front of childLevel2b. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } + + // Background layer (RED) + // Foregroud layer (GREEN) + Transaction{}.reparent(childLevel1, nullptr).apply(); + + // Background layer (RED) + // Foregroud layer (GREEN) + // child level 1 (WHITE) + // child level 2 back (BLUE) + // child level 3 (GREEN) (relative to child level 2b) + // child level 2 front (BLACK) + Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply(); + + { + // Nothing should change at this point since relative z info was preserved. + ScreenCapture::captureScreen(&sc); + sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); + } +} +} // namespace android diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h new file mode 100644 index 0000000000..8fdcde40b6 --- /dev/null +++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ANDROID_TRANSACTION_TEST_HARNESSES +#define ANDROID_TRANSACTION_TEST_HARNESSES + +/*#include <algorithm> +#include <chrono> +#include <cinttypes> +#include <functional> +#include <limits> +#include <ostream> + +#include <android/native_window.h> + +#include <binder/ProcessState.h> +#include <gui/BufferItemConsumer.h> +#include <gui/IProducerListener.h> +#include <gui/ISurfaceComposer.h> +#include <gui/LayerState.h> +#include <gui/Surface.h> +#include <gui/SurfaceComposerClient.h> +#include <hardware/hwcomposer_defs.h> +#include <private/android_filesystem_config.h> +#include <private/gui/ComposerService.h> + +#include <ui/DisplayInfo.h> + +#include <math.h> +#include <math/vec3.h> +#include <sys/types.h> +#include <unistd.h> + +#include "BufferGenerator.h" +*/ +#include "LayerTransactionTest.h" +/*#include "utils/CallbackUtils.h" +#include "utils/ColorUtils.h" +#include "utils/ScreenshotUtils.h" +#include "utils/TransactionUtils.h" +*/ +namespace android { + +using android::hardware::graphics::common::V1_1::BufferUsage; + +class LayerRenderPathTestHarness { +public: + LayerRenderPathTestHarness(LayerTransactionTest* delegate, RenderPath renderPath) + : mDelegate(delegate), mRenderPath(renderPath) {} + + std::unique_ptr<ScreenCapture> getScreenCapture() { + switch (mRenderPath) { + case RenderPath::SCREENSHOT: + return mDelegate->screenshot(); + case RenderPath::VIRTUAL_DISPLAY: + + const auto mainDisplay = SurfaceComposerClient::getInternalDisplayToken(); + DisplayInfo mainDisplayInfo; + SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo); + + sp<IBinder> vDisplay; + sp<IGraphicBufferProducer> producer; + sp<IGraphicBufferConsumer> consumer; + sp<BufferItemConsumer> itemConsumer; + BufferQueue::createBufferQueue(&producer, &consumer); + + consumer->setConsumerName(String8("Virtual disp consumer")); + consumer->setDefaultBufferSize(mainDisplayInfo.w, mainDisplayInfo.h); + + itemConsumer = new BufferItemConsumer(consumer, + // Sample usage bits from screenrecord + GRALLOC_USAGE_HW_VIDEO_ENCODER | + GRALLOC_USAGE_SW_READ_OFTEN); + + vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), + false /*secure*/); + + SurfaceComposerClient::Transaction t; + t.setDisplaySurface(vDisplay, producer); + t.setDisplayLayerStack(vDisplay, 0); + t.setDisplayProjection(vDisplay, mainDisplayInfo.orientation, + Rect(mainDisplayInfo.viewportW, mainDisplayInfo.viewportH), + Rect(mainDisplayInfo.w, mainDisplayInfo.h)); + t.apply(); + SurfaceComposerClient::Transaction().apply(true); + BufferItem item; + itemConsumer->acquireBuffer(&item, 0, true); + auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer); + itemConsumer->releaseBuffer(item); + SurfaceComposerClient::destroyDisplay(vDisplay); + return sc; + } + } + +protected: + LayerTransactionTest* mDelegate; + RenderPath mRenderPath; +}; + +class LayerTypeTransactionHarness : public LayerTransactionTest { +public: + LayerTypeTransactionHarness(uint32_t layerType) : mLayerType(layerType) {} + + sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, + uint32_t flags = 0, SurfaceControl* parent = nullptr) { + // if the flags already have a layer type specified, return an error + if (flags & ISurfaceComposerClient::eFXSurfaceMask) { + return nullptr; + } + return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType, parent); + } + + void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth, + int32_t bufferHeight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color, + bufferWidth, bufferHeight)); + } + + void fillLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, + int32_t bufferHeight, const Color& topLeft, const Color& topRight, + const Color& bottomLeft, const Color& bottomRight) { + ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer, + bufferWidth, bufferHeight, + topLeft, topRight, + bottomLeft, bottomRight)); + } + +protected: + uint32_t mLayerType; +}; +} // namespace android +#endif diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp deleted file mode 100644 index d765f68a46..0000000000 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ /dev/null @@ -1,5593 +0,0 @@ -/* - * Copyright (C) 2011 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 <algorithm> -#include <chrono> -#include <cinttypes> -#include <functional> -#include <limits> -#include <ostream> - -#include <gtest/gtest.h> - -#include <android/native_window.h> - -#include <binder/ProcessState.h> -#include <gui/BufferItemConsumer.h> -#include <gui/IProducerListener.h> -#include <gui/ISurfaceComposer.h> -#include <gui/LayerState.h> -#include <gui/Surface.h> -#include <gui/SurfaceComposerClient.h> -#include <hardware/hwcomposer_defs.h> -#include <private/android_filesystem_config.h> -#include <private/gui/ComposerService.h> - -#include <ui/DisplayInfo.h> - -#include <math.h> -#include <math/vec3.h> -#include <sys/types.h> -#include <unistd.h> - -#include "BufferGenerator.h" -#include "utils/CallbackUtils.h" -#include "utils/ColorUtils.h" -#include "utils/ScreenshotUtils.h" -#include "utils/TransactionUtils.h" - -namespace android { - -using android::hardware::graphics::common::V1_1::BufferUsage; - -class LayerTransactionTest : public ::testing::Test { -protected: - void SetUp() override { - mClient = new SurfaceComposerClient; - ASSERT_EQ(NO_ERROR, mClient->initCheck()) << "failed to create SurfaceComposerClient"; - - ASSERT_NO_FATAL_FAILURE(SetUpDisplay()); - - sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - ASSERT_NO_FATAL_FAILURE(sf->getColorManagement(&mColorManagementUsed)); - } - - virtual void TearDown() { - mBlackBgSurface = 0; - mClient->dispose(); - mClient = 0; - } - - virtual sp<SurfaceControl> createLayer(const sp<SurfaceComposerClient>& client, - const char* name, uint32_t width, uint32_t height, - uint32_t flags = 0, SurfaceControl* parent = nullptr) { - auto layer = - createSurface(client, name, width, height, PIXEL_FORMAT_RGBA_8888, flags, parent); - - Transaction t; - t.setLayerStack(layer, mDisplayLayerStack).setLayer(layer, mLayerZBase); - - status_t error = t.apply(); - if (error != NO_ERROR) { - ADD_FAILURE() << "failed to initialize SurfaceControl"; - layer.clear(); - } - - return layer; - } - - virtual sp<SurfaceControl> createSurface(const sp<SurfaceComposerClient>& client, - const char* name, uint32_t width, uint32_t height, - PixelFormat format, uint32_t flags, - SurfaceControl* parent = nullptr) { - auto layer = client->createSurface(String8(name), width, height, format, flags, parent); - EXPECT_NE(nullptr, layer.get()) << "failed to create SurfaceControl"; - return layer; - } - - virtual sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, - uint32_t flags = 0, SurfaceControl* parent = nullptr) { - return createLayer(mClient, name, width, height, flags, parent); - } - - sp<SurfaceControl> createColorLayer(const char* name, const Color& color, - SurfaceControl* parent = nullptr) { - auto colorLayer = createSurface(mClient, name, 0 /* buffer width */, 0 /* buffer height */, - PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, parent); - asTransaction([&](Transaction& t) { - t.setColor(colorLayer, half3{color.r / 255.0f, color.g / 255.0f, color.b / 255.0f}); - t.setAlpha(colorLayer, color.a / 255.0f); - }); - return colorLayer; - } - - ANativeWindow_Buffer getBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { - // wait for previous transactions (such as setSize) to complete - Transaction().apply(true); - - ANativeWindow_Buffer buffer = {}; - EXPECT_EQ(NO_ERROR, layer->getSurface()->lock(&buffer, nullptr)); - - return buffer; - } - - void postBufferQueueLayerBuffer(const sp<SurfaceControl>& layer) { - ASSERT_EQ(NO_ERROR, layer->getSurface()->unlockAndPost()); - - // wait for the newly posted buffer to be latched - waitForLayerBuffers(); - } - - virtual void fillBufferQueueLayerColor(const sp<SurfaceControl>& layer, const Color& color, - int32_t bufferWidth, int32_t bufferHeight) { - ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); - TransactionUtils::fillANativeWindowBufferColor(buffer, - Rect(0, 0, bufferWidth, bufferHeight), - color); - postBufferQueueLayerBuffer(layer); - } - - virtual void fillBufferStateLayerColor(const sp<SurfaceControl>& layer, const Color& color, - int32_t bufferWidth, int32_t bufferHeight) { - sp<GraphicBuffer> buffer = - new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), - color); - Transaction().setBuffer(layer, buffer).apply(); - } - - void fillLayerColor(uint32_t mLayerType, const sp<SurfaceControl>& layer, const Color& color, - int32_t bufferWidth, int32_t bufferHeight) { - switch (mLayerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - fillBufferQueueLayerColor(layer, color, bufferWidth, bufferHeight); - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - fillBufferStateLayerColor(layer, color, bufferWidth, bufferHeight); - break; - default: - ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; - } - } - - void fillLayerQuadrant(uint32_t mLayerType, const sp<SurfaceControl>& layer, - int32_t bufferWidth, int32_t bufferHeight, const Color& topLeft, - const Color& topRight, const Color& bottomLeft, - const Color& bottomRight) { - switch (mLayerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - fillBufferQueueLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, - bottomLeft, bottomRight); - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - fillBufferStateLayerQuadrant(layer, bufferWidth, bufferHeight, topLeft, topRight, - bottomLeft, bottomRight); - break; - default: - ASSERT_TRUE(false) << "unsupported layer type: " << mLayerType; - } - } - - virtual void fillBufferQueueLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, - int32_t bufferHeight, const Color& topLeft, - const Color& topRight, const Color& bottomLeft, - const Color& bottomRight) { - ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); - ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); - - const int32_t halfW = bufferWidth / 2; - const int32_t halfH = bufferHeight / 2; - TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); - TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), - topRight); - TransactionUtils::fillANativeWindowBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), - bottomLeft); - TransactionUtils::fillANativeWindowBufferColor(buffer, - Rect(halfW, halfH, bufferWidth, - bufferHeight), - bottomRight); - - postBufferQueueLayerBuffer(layer); - } - - virtual void fillBufferStateLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, - int32_t bufferHeight, const Color& topLeft, - const Color& topRight, const Color& bottomLeft, - const Color& bottomRight) { - sp<GraphicBuffer> buffer = - new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - - ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); - - const int32_t halfW = bufferWidth / 2; - const int32_t halfH = bufferHeight / 2; - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, halfW, halfH), topLeft); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(halfW, 0, bufferWidth, halfH), - topRight); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, halfH, halfW, bufferHeight), - bottomLeft); - TransactionUtils::fillGraphicBufferColor(buffer, - Rect(halfW, halfH, bufferWidth, bufferHeight), - bottomRight); - - Transaction().setBuffer(layer, buffer).setSize(layer, bufferWidth, bufferHeight).apply(); - } - - std::unique_ptr<ScreenCapture> screenshot() { - std::unique_ptr<ScreenCapture> screenshot; - ScreenCapture::captureScreen(&screenshot); - return screenshot; - } - - void asTransaction(const std::function<void(Transaction&)>& exec) { - Transaction t; - exec(t); - t.apply(true); - } - - static status_t getBuffer(sp<GraphicBuffer>* outBuffer, sp<Fence>* outFence) { - static BufferGenerator bufferGenerator; - return bufferGenerator.get(outBuffer, outFence); - } - - sp<SurfaceComposerClient> mClient; - - sp<IBinder> mDisplay; - uint32_t mDisplayWidth; - uint32_t mDisplayHeight; - uint32_t mDisplayLayerStack; - Rect mDisplayRect = Rect::INVALID_RECT; - - // leave room for ~256 layers - const int32_t mLayerZBase = std::numeric_limits<int32_t>::max() - 256; - - sp<SurfaceControl> mBlackBgSurface; - bool mColorManagementUsed; - -private: - void SetUpDisplay() { - mDisplay = mClient->getInternalDisplayToken(); - ASSERT_FALSE(mDisplay == nullptr) << "failed to get display"; - - // get display width/height - DisplayInfo info; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(mDisplay, &info)); - mDisplayWidth = info.w; - mDisplayHeight = info.h; - mDisplayRect = - Rect(static_cast<int32_t>(mDisplayWidth), static_cast<int32_t>(mDisplayHeight)); - - // After a new buffer is queued, SurfaceFlinger is notified and will - // latch the new buffer on next vsync. Let's heuristically wait for 3 - // vsyncs. - mBufferPostDelay = int32_t(1e6 / info.fps) * 3; - - mDisplayLayerStack = 0; - - mBlackBgSurface = - createSurface(mClient, "BaseSurface", 0 /* buffer width */, 0 /* buffer height */, - PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor); - - // set layer stack (b/68888219) - Transaction t; - t.setDisplayLayerStack(mDisplay, mDisplayLayerStack); - t.setCrop_legacy(mBlackBgSurface, Rect(0, 0, mDisplayWidth, mDisplayHeight)); - t.setLayerStack(mBlackBgSurface, mDisplayLayerStack); - t.setColor(mBlackBgSurface, half3{0, 0, 0}); - t.setLayer(mBlackBgSurface, mLayerZBase); - t.apply(); - } - - void waitForLayerBuffers() { - // Request an empty transaction to get applied synchronously to ensure the buffer is - // latched. - Transaction().apply(true); - usleep(mBufferPostDelay); - } - - int32_t mBufferPostDelay; - - friend class LayerRenderPathTestHarness; -}; - -class LayerRenderPathTestHarness { -public: - LayerRenderPathTestHarness(LayerTransactionTest* delegate, RenderPath renderPath) - : mDelegate(delegate), mRenderPath(renderPath) {} - - std::unique_ptr<ScreenCapture> getScreenCapture() { - switch (mRenderPath) { - case RenderPath::SCREENSHOT: - return mDelegate->screenshot(); - case RenderPath::VIRTUAL_DISPLAY: - - const auto mainDisplay = SurfaceComposerClient::getInternalDisplayToken(); - DisplayInfo mainDisplayInfo; - SurfaceComposerClient::getDisplayInfo(mainDisplay, &mainDisplayInfo); - - sp<IBinder> vDisplay; - sp<IGraphicBufferProducer> producer; - sp<IGraphicBufferConsumer> consumer; - sp<BufferItemConsumer> itemConsumer; - BufferQueue::createBufferQueue(&producer, &consumer); - - consumer->setConsumerName(String8("Virtual disp consumer")); - consumer->setDefaultBufferSize(mainDisplayInfo.w, mainDisplayInfo.h); - - itemConsumer = new BufferItemConsumer(consumer, - // Sample usage bits from screenrecord - GRALLOC_USAGE_HW_VIDEO_ENCODER | - GRALLOC_USAGE_SW_READ_OFTEN); - - vDisplay = SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), - false /*secure*/); - - SurfaceComposerClient::Transaction t; - t.setDisplaySurface(vDisplay, producer); - t.setDisplayLayerStack(vDisplay, 0); - t.setDisplayProjection(vDisplay, mainDisplayInfo.orientation, - Rect(mainDisplayInfo.viewportW, mainDisplayInfo.viewportH), - Rect(mainDisplayInfo.w, mainDisplayInfo.h)); - t.apply(); - SurfaceComposerClient::Transaction().apply(true); - BufferItem item; - itemConsumer->acquireBuffer(&item, 0, true); - auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer); - itemConsumer->releaseBuffer(item); - SurfaceComposerClient::destroyDisplay(vDisplay); - return sc; - } - } - -protected: - LayerTransactionTest* mDelegate; - RenderPath mRenderPath; -}; - -class LayerTypeTransactionHarness : public LayerTransactionTest { -public: - LayerTypeTransactionHarness(uint32_t layerType) : mLayerType(layerType) {} - - sp<SurfaceControl> createLayer(const char* name, uint32_t width, uint32_t height, - uint32_t flags = 0, SurfaceControl* parent = nullptr) { - // if the flags already have a layer type specified, return an error - if (flags & ISurfaceComposerClient::eFXSurfaceMask) { - return nullptr; - } - return LayerTransactionTest::createLayer(name, width, height, flags | mLayerType, parent); - } - - void fillLayerColor(const sp<SurfaceControl>& layer, const Color& color, int32_t bufferWidth, - int32_t bufferHeight) { - ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerColor(mLayerType, layer, color, - bufferWidth, bufferHeight)); - } - - void fillLayerQuadrant(const sp<SurfaceControl>& layer, int32_t bufferWidth, - int32_t bufferHeight, const Color& topLeft, const Color& topRight, - const Color& bottomLeft, const Color& bottomRight) { - ASSERT_NO_FATAL_FAILURE(LayerTransactionTest::fillLayerQuadrant(mLayerType, layer, - bufferWidth, bufferHeight, - topLeft, topRight, - bottomLeft, bottomRight)); - } - -protected: - uint32_t mLayerType; -}; - -class LayerTypeTransactionTest : public LayerTypeTransactionHarness, - public ::testing::WithParamInterface<uint32_t> { -public: - LayerTypeTransactionTest() : LayerTypeTransactionHarness(GetParam()) {} -}; - -class LayerTypeAndRenderTypeTransactionTest - : public LayerTypeTransactionHarness, - public ::testing::WithParamInterface<std::tuple<uint32_t, RenderPath>> { -public: - LayerTypeAndRenderTypeTransactionTest() - : LayerTypeTransactionHarness(std::get<0>(GetParam())), - mRenderPathHarness(LayerRenderPathTestHarness(this, std::get<1>(GetParam()))) {} - - std::unique_ptr<ScreenCapture> getScreenCapture() { - return mRenderPathHarness.getScreenCapture(); - } - -protected: - LayerRenderPathTestHarness mRenderPathHarness; -}; - -::testing::Environment* const binderEnv = - ::testing::AddGlobalTestEnvironment(new BinderEnvironment()); - -class LayerRenderTypeTransactionTest : public LayerTransactionTest, - public ::testing::WithParamInterface<RenderPath> { -public: - LayerRenderTypeTransactionTest() : mHarness(LayerRenderPathTestHarness(this, GetParam())) {} - - std::unique_ptr<ScreenCapture> getScreenCapture() { return mHarness.getScreenCapture(); } - void setRelativeZBasicHelper(uint32_t layerType); - void setRelativeZGroupHelper(uint32_t layerType); - void setAlphaBasicHelper(uint32_t layerType); - void setBackgroundColorHelper(uint32_t layerType, bool priorColor, bool bufferFill, float alpha, - Color finalColor); - -protected: - LayerRenderPathTestHarness mHarness; -}; - -INSTANTIATE_TEST_CASE_P( - LayerTypeAndRenderTypeTransactionTests, LayerTypeAndRenderTypeTransactionTest, - ::testing::Combine( - ::testing::Values( - static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue), - static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState)), - ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT))); - -INSTANTIATE_TEST_CASE_P(LayerRenderTypeTransactionTests, LayerRenderTypeTransactionTest, - ::testing::Values(RenderPath::VIRTUAL_DISPLAY, RenderPath::SCREENSHOT)); - -INSTANTIATE_TEST_CASE_P( - LayerTypeTransactionTests, LayerTypeTransactionTest, - ::testing::Values(static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferQueue), - static_cast<uint32_t>(ISurfaceComposerClient::eFXSurfaceBufferState))); - -TEST_P(LayerRenderTypeTransactionTest, SetPositionBasic_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - { - SCOPED_TRACE("default position"); - const Rect rect(0, 0, 32, 32); - auto shot = getScreenCapture(); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } - - Transaction().setPosition(layer, 5, 10).apply(); - { - SCOPED_TRACE("new position"); - const Rect rect(5, 10, 37, 42); - auto shot = getScreenCapture(); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetPositionRounding_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // GLES requires only 4 bits of subpixel precision during rasterization - // XXX GLES composition does not match HWC composition due to precision - // loss (b/69315223) - const float epsilon = 1.0f / 16.0f; - Transaction().setPosition(layer, 0.5f - epsilon, 0.5f - epsilon).apply(); - { - SCOPED_TRACE("rounding down"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setPosition(layer, 0.5f + epsilon, 0.5f + epsilon).apply(); - { - SCOPED_TRACE("rounding up"); - getScreenCapture()->expectColor(Rect(1, 1, 33, 33), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetPositionOutOfBounds_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - Transaction().setPosition(layer, -32, -32).apply(); - { - SCOPED_TRACE("negative coordinates"); - getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); - } - - Transaction().setPosition(layer, mDisplayWidth, mDisplayHeight).apply(); - { - SCOPED_TRACE("positive coordinates"); - getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetPositionPartiallyOutOfBounds_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // partially out of bounds - Transaction().setPosition(layer, -30, -30).apply(); - { - SCOPED_TRACE("negative coordinates"); - getScreenCapture()->expectColor(Rect(0, 0, 2, 2), Color::RED); - } - - Transaction().setPosition(layer, mDisplayWidth - 2, mDisplayHeight - 2).apply(); - { - SCOPED_TRACE("positive coordinates"); - getScreenCapture()->expectColor(Rect(mDisplayWidth - 2, mDisplayHeight - 2, mDisplayWidth, - mDisplayHeight), - Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetPositionWithResize_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setPosition is applied immediately by default, with or without resize - // pending - Transaction().setPosition(layer, 5, 10).setSize(layer, 64, 64).apply(); - { - SCOPED_TRACE("resize pending"); - auto shot = getScreenCapture(); - const Rect rect(5, 10, 37, 42); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("resize applied"); - getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - Transaction().setSize(layer, 64, 64).apply(); - { - SCOPED_TRACE("resize pending"); - auto shot = getScreenCapture(); - const Rect rect(0, 0, 32, 32); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("resize applied"); - auto shot = getScreenCapture(); - const Rect rect(0, 0, 64, 64); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetSizeInvalid) { - // cannot test robustness against invalid sizes (zero or really huge) -} - -TEST_P(LayerRenderTypeTransactionTest, SetSizeWithScaleToWindow_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setSize is immediate with SCALE_TO_WINDOW, unlike setPosition - Transaction() - .setSize(layer, 64, 64) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .apply(); - getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED); -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZBasic) { - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - - Transaction().setLayer(layerR, mLayerZBase + 1).apply(); - { - SCOPED_TRACE("layerR"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setLayer(layerG, mLayerZBase + 2).apply(); - { - SCOPED_TRACE("layerG"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::GREEN); - } -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetZNegative) { - sp<SurfaceControl> parent = - LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceContainer); - Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply(); - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - - Transaction() - .reparent(layerR, parent->getHandle()) - .reparent(layerG, parent->getHandle()) - .apply(); - Transaction().setLayer(layerR, -1).setLayer(layerG, -2).apply(); - { - SCOPED_TRACE("layerR"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setLayer(layerR, -3).apply(); - { - SCOPED_TRACE("layerG"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::GREEN); - } -} - -void LayerRenderTypeTransactionTest::setRelativeZBasicHelper(uint32_t layerType) { - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32)); - - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - Transaction() - .setPosition(layerG, 16, 16) - .setRelativeLayer(layerG, layerR->getHandle(), 1) - .apply(); - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(16, 16, 48, 48)) - .setRelativeLayer(layerG, layerR->getHandle(), 1) - .apply(); - break; - default: - ASSERT_FALSE(true) << "Unsupported layer type"; - } - { - SCOPED_TRACE("layerG above"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 16, 16), Color::RED); - shot->expectColor(Rect(16, 16, 48, 48), Color::GREEN); - } - - Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).apply(); - { - SCOPED_TRACE("layerG below"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectColor(Rect(32, 32, 48, 48), Color::GREEN); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferQueue) { - ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); -} - -TEST_P(LayerRenderTypeTransactionTest, SetRelativeZBasic_BufferState) { - ASSERT_NO_FATAL_FAILURE(setRelativeZBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); -} - -TEST_P(LayerTypeTransactionTest, SetRelativeZNegative) { - sp<SurfaceControl> parent = - LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceContainer); - Transaction().setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)).apply(); - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - sp<SurfaceControl> layerB; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test B", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerB, Color::BLUE, 32, 32)); - - Transaction() - .reparent(layerB, parent->getHandle()) - .apply(); - - // layerR = mLayerZBase, layerG = layerR - 1, layerB = -2 - Transaction().setRelativeLayer(layerG, layerR->getHandle(), -1).setLayer(layerB, -2).apply(); - - std::unique_ptr<ScreenCapture> screenshot; - // only layerB is in this range - sp<IBinder> parentHandle = parent->getHandle(); - ScreenCapture::captureLayers(&screenshot, parentHandle, Rect(0, 0, 32, 32)); - screenshot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); -} - -TEST_P(LayerTypeTransactionTest, SetLayerAndRelative) { - sp<SurfaceControl> parent = - LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor); - - sp<SurfaceControl> childLayer; - ASSERT_NO_FATAL_FAILURE( - childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */, - 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor, - parent.get())); - Transaction() - .setColor(childLayer, half3{1.0f, 0.0f, 0.0f}) - .setColor(parent, half3{0.0f, 0.0f, 0.0f}) - .show(childLayer) - .show(parent) - .setCrop_legacy(parent, Rect(0, 0, mDisplayWidth, mDisplayHeight)) - .setCrop_legacy(childLayer, Rect(0, 0, 20, 30)) - .apply(); - - Transaction() - .setRelativeLayer(childLayer, parent->getHandle(), -1) - .setLayer(childLayer, 1) - .apply(); - - { - SCOPED_TRACE("setLayer above"); - // Set layer should get applied and place the child above. - std::unique_ptr<ScreenCapture> screenshot; - ScreenCapture::captureScreen(&screenshot); - screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED); - } - - Transaction() - .setLayer(childLayer, 1) - .setRelativeLayer(childLayer, parent->getHandle(), -1) - .apply(); - - { - SCOPED_TRACE("setRelative below"); - // Set relative layer should get applied and place the child below. - std::unique_ptr<ScreenCapture> screenshot; - ScreenCapture::captureScreen(&screenshot); - screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK); - } -} - -TEST_P(LayerTypeTransactionTest, HideRelativeParentHidesLayer) { - sp<SurfaceControl> parent = - LayerTransactionTest::createLayer("Parent", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor); - sp<SurfaceControl> relativeParent = - LayerTransactionTest::createLayer("RelativeParent", 0 /* buffer width */, - 0 /* buffer height */, ISurfaceComposerClient::eFXSurfaceColor); - - sp<SurfaceControl> childLayer; - ASSERT_NO_FATAL_FAILURE( - childLayer = LayerTransactionTest::createLayer("childLayer", 0 /* buffer width */, - 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor, - parent.get())); - Transaction() - .setColor(childLayer, half3{1.0f, 0.0f, 0.0f}) - .setColor(parent, half3{0.0f, 0.0f, 0.0f}) - .setColor(relativeParent, half3{0.0f, 1.0f, 0.0f}) - .show(childLayer) - .show(parent) - .show(relativeParent) - .setLayer(parent, mLayerZBase - 1) - .setLayer(relativeParent, mLayerZBase) - .apply(); - - Transaction() - .setRelativeLayer(childLayer, relativeParent->getHandle(), 1) - .apply(); - - { - SCOPED_TRACE("setLayer above"); - // Set layer should get applied and place the child above. - std::unique_ptr<ScreenCapture> screenshot; - ScreenCapture::captureScreen(&screenshot); - screenshot->expectColor(Rect(0, 0, 20, 30), Color::RED); - } - - Transaction() - .hide(relativeParent) - .apply(); - - { - SCOPED_TRACE("hide relative parent"); - // The relative should no longer be visible. - std::unique_ptr<ScreenCapture> screenshot; - ScreenCapture::captureScreen(&screenshot); - screenshot->expectColor(Rect(0, 0, 20, 30), Color::BLACK); - } -} - -void LayerRenderTypeTransactionTest::setRelativeZGroupHelper(uint32_t layerType) { - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - sp<SurfaceControl> layerB; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerG, Color::GREEN, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerB = createLayer("test", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layerB, Color::BLUE, 32, 32)); - - // layerR = 0, layerG = layerR + 3, layerB = 2 - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - Transaction() - .setPosition(layerG, 8, 8) - .setRelativeLayer(layerG, layerR->getHandle(), 3) - .setPosition(layerB, 16, 16) - .setLayer(layerB, mLayerZBase + 2) - .apply(); - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction() - .setFrame(layerR, Rect(0, 0, 32, 32)) - .setFrame(layerG, Rect(8, 8, 40, 40)) - .setRelativeLayer(layerG, layerR->getHandle(), 3) - .setFrame(layerB, Rect(16, 16, 48, 48)) - .setLayer(layerB, mLayerZBase + 2) - .apply(); - break; - default: - ASSERT_FALSE(true) << "Unsupported layer type"; - } - - { - SCOPED_TRACE("(layerR < layerG) < layerB"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 8, 8), Color::RED); - shot->expectColor(Rect(8, 8, 16, 16), Color::GREEN); - shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE); - } - - // layerR = 4, layerG = layerR + 3, layerB = 2 - Transaction().setLayer(layerR, mLayerZBase + 4).apply(); - { - SCOPED_TRACE("layerB < (layerR < layerG)"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 8, 8), Color::RED); - shot->expectColor(Rect(8, 8, 40, 40), Color::GREEN); - shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE); - } - - // layerR = 4, layerG = layerR - 3, layerB = 2 - Transaction().setRelativeLayer(layerG, layerR->getHandle(), -3).apply(); - { - SCOPED_TRACE("layerB < (layerG < layerR)"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectColor(Rect(32, 32, 40, 40), Color::GREEN); - shot->expectColor(Rect(40, 40, 48, 48), Color::BLUE); - } - - // restore to absolute z - // layerR = 4, layerG = 0, layerB = 2 - Transaction().setLayer(layerG, mLayerZBase).apply(); - { - SCOPED_TRACE("layerG < layerB < layerR"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectColor(Rect(32, 32, 48, 48), Color::BLUE); - } - - // layerR should not affect layerG anymore - // layerR = 1, layerG = 0, layerB = 2 - Transaction().setLayer(layerR, mLayerZBase + 1).apply(); - { - SCOPED_TRACE("layerG < layerR < layerB"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 16, 16), Color::RED); - shot->expectColor(Rect(16, 16, 48, 48), Color::BLUE); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferQueue) { - ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); -} - -TEST_P(LayerRenderTypeTransactionTest, SetRelativeZGroup_BufferState) { - ASSERT_NO_FATAL_FAILURE(setRelativeZGroupHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetRelativeZBug64572777) { - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - - Transaction() - .setPosition(layerG, 16, 16) - .setRelativeLayer(layerG, layerR->getHandle(), 1) - .apply(); - - layerG.clear(); - // layerG should have been removed - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsHidden) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); - - Transaction().setFlags(layer, layer_state_t::eLayerHidden, layer_state_t::eLayerHidden).apply(); - { - SCOPED_TRACE("layer hidden"); - getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); - } - - Transaction().setFlags(layer, 0, layer_state_t::eLayerHidden).apply(); - { - SCOPED_TRACE("layer shown"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetFlagsOpaque) { - const Color translucentRed = {100, 0, 0, 100}; - sp<SurfaceControl> layerR; - sp<SurfaceControl> layerG; - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerR, translucentRed, 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerG = createLayer("test G", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerG, Color::GREEN, 32, 32)); - - Transaction() - .setLayer(layerR, mLayerZBase + 1) - .setFlags(layerR, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque) - .apply(); - { - SCOPED_TRACE("layerR opaque"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, 0, 0, 255}); - } - - Transaction().setFlags(layerR, 0, layer_state_t::eLayerOpaque).apply(); - { - SCOPED_TRACE("layerR translucent"); - const uint8_t g = uint8_t(255 - translucentRed.a); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {100, g, 0, 255}); - } -} - -TEST_P(LayerTypeTransactionTest, SetFlagsSecure) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); - - sp<ISurfaceComposer> composer = ComposerService::getComposerService(); - sp<GraphicBuffer> outBuffer; - Transaction() - .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) - .apply(true); - ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); - - Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true); - ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); -} - -TEST_F(LayerTransactionTest, SetFlagsSecureEUidSystem) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - sp<ISurfaceComposer> composer = ComposerService::getComposerService(); - sp<GraphicBuffer> outBuffer; - Transaction() - .setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure) - .apply(true); - ASSERT_EQ(PERMISSION_DENIED, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); - - UIDFaker f(AID_SYSTEM); - - // By default the system can capture screenshots with secure layers but they - // will be blacked out - ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, false)); - - { - SCOPED_TRACE("as system"); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } - - // Here we pass captureSecureLayers = true and since we are AID_SYSTEM we should be able - // to receive them...we are expected to take care with the results. - bool outCapturedSecureLayers; - ASSERT_EQ(NO_ERROR, - composer->captureScreen(mDisplay, &outBuffer, outCapturedSecureLayers, - ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888, Rect(), 0, - 0, false, ISurfaceComposer::eRotateNone, true)); - ASSERT_EQ(true, outCapturedSecureLayers); - ScreenCapture sc(outBuffer); - sc.expectColor(Rect(0, 0, 32, 32), Color::RED); -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferQueue) { - const Rect top(0, 0, 32, 16); - const Rect bottom(0, 16, 32, 32); - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - - ANativeWindow_Buffer buffer; - ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE( - TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE( - TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::RED)); - // setTransparentRegionHint always applies to the following buffer - Transaction().setTransparentRegionHint(layer, Region(top)).apply(); - ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); - { - SCOPED_TRACE("top transparent"); - auto shot = getScreenCapture(); - shot->expectColor(top, Color::BLACK); - shot->expectColor(bottom, Color::RED); - } - - Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); - { - SCOPED_TRACE("transparent region hint pending"); - auto shot = getScreenCapture(); - shot->expectColor(top, Color::BLACK); - shot->expectColor(bottom, Color::RED); - } - - ASSERT_NO_FATAL_FAILURE(buffer = getBufferQueueLayerBuffer(layer)); - ASSERT_NO_FATAL_FAILURE( - TransactionUtils::fillANativeWindowBufferColor(buffer, top, Color::RED)); - ASSERT_NO_FATAL_FAILURE( - TransactionUtils::fillANativeWindowBufferColor(buffer, bottom, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(postBufferQueueLayerBuffer(layer)); - { - SCOPED_TRACE("bottom transparent"); - auto shot = getScreenCapture(); - shot->expectColor(top, Color::RED); - shot->expectColor(bottom, Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState) { - const Rect top(0, 0, 32, 16); - const Rect bottom(0, 16, 32, 32); - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - - ASSERT_NO_FATAL_FAILURE( - TransactionUtils::fillGraphicBufferColor(buffer, top, Color::TRANSPARENT)); - ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::RED)); - Transaction() - .setTransparentRegionHint(layer, Region(top)) - .setBuffer(layer, buffer) - .setFrame(layer, Rect(0, 0, 32, 32)) - .apply(); - { - SCOPED_TRACE("top transparent"); - auto shot = getScreenCapture(); - shot->expectColor(top, Color::BLACK); - shot->expectColor(bottom, Color::RED); - } - - Transaction().setTransparentRegionHint(layer, Region(bottom)).apply(); - { - SCOPED_TRACE("transparent region hint intermediate"); - auto shot = getScreenCapture(); - shot->expectColor(top, Color::BLACK); - shot->expectColor(bottom, Color::BLACK); - } - - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - - ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, top, Color::RED)); - ASSERT_NO_FATAL_FAILURE( - TransactionUtils::fillGraphicBufferColor(buffer, bottom, Color::TRANSPARENT)); - Transaction().setBuffer(layer, buffer).apply(); - { - SCOPED_TRACE("bottom transparent"); - auto shot = getScreenCapture(); - shot->expectColor(top, Color::RED); - shot->expectColor(bottom, Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferQueue) { - sp<SurfaceControl> layerTransparent; - sp<SurfaceControl> layerR; - ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); - ASSERT_NO_FATAL_FAILURE(layerR = createLayer("test R", 32, 32)); - - // check that transparent region hint is bound by the layer size - Transaction() - .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setPosition(layerR, 16, 16) - .setLayer(layerR, mLayerZBase + 1) - .apply(); - ASSERT_NO_FATAL_FAILURE( - fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layerR, Color::RED, 32, 32)); - getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED); -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintOutOfBounds_BufferState) { - sp<SurfaceControl> layerTransparent; - sp<SurfaceControl> layerR; - ASSERT_NO_FATAL_FAILURE(layerTransparent = createLayer("test transparent", 32, 32)); - ASSERT_NO_FATAL_FAILURE( - layerR = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - // check that transparent region hint is bound by the layer size - Transaction() - .setTransparentRegionHint(layerTransparent, Region(mDisplayRect)) - .setFrame(layerR, Rect(16, 16, 48, 48)) - .setLayer(layerR, mLayerZBase + 1) - .apply(); - ASSERT_NO_FATAL_FAILURE( - fillBufferQueueLayerColor(layerTransparent, Color::TRANSPARENT, 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layerR, Color::RED, 32, 32)); - getScreenCapture()->expectColor(Rect(16, 16, 48, 48), Color::RED); -} - -void LayerRenderTypeTransactionTest::setAlphaBasicHelper(uint32_t layerType) { - sp<SurfaceControl> layer1; - sp<SurfaceControl> layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer("test 1", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer("test 2", 32, 32, layerType)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer1, {64, 0, 0, 255}, 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layerType, layer2, {0, 64, 0, 255}, 32, 32)); - - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - Transaction() - .setAlpha(layer1, 0.25f) - .setAlpha(layer2, 0.75f) - .setPosition(layer2, 16, 0) - .setLayer(layer2, mLayerZBase + 1) - .apply(); - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - Transaction() - .setAlpha(layer1, 0.25f) - .setAlpha(layer2, 0.75f) - .setFrame(layer1, Rect(0, 0, 32, 32)) - .setFrame(layer2, Rect(16, 0, 48, 32)) - .setLayer(layer2, mLayerZBase + 1) - .apply(); - break; - default: - ASSERT_FALSE(true) << "Unsupported layer type"; - } - { - auto shot = getScreenCapture(); - uint8_t r = 16; // 64 * 0.25f - uint8_t g = 48; // 64 * 0.75f - shot->expectColor(Rect(0, 0, 16, 32), {r, 0, 0, 255}); - shot->expectColor(Rect(32, 0, 48, 32), {0, g, 0, 255}); - - r /= 4; // r * (1.0f - 0.75f) - shot->expectColor(Rect(16, 0, 32, 32), {r, g, 0, 255}); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferQueue) { - ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue)); -} - -TEST_P(LayerRenderTypeTransactionTest, SetAlphaBasic_BufferState) { - ASSERT_NO_FATAL_FAILURE(setAlphaBasicHelper(ISurfaceComposerClient::eFXSurfaceBufferState)); -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetAlphaClamped) { - const Color color = {64, 0, 0, 255}; - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, color, 32, 32)); - - Transaction().setAlpha(layer, 2.0f).apply(); - { - SCOPED_TRACE("clamped to 1.0f"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), color); - } - - Transaction().setAlpha(layer, -1.0f).apply(); - { - SCOPED_TRACE("clamped to 0.0f"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadius) { - sp<SurfaceControl> layer; - const uint8_t size = 64; - const uint8_t testArea = 4; - const float cornerRadius = 20.0f; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", size, size)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, size, size)); - - Transaction() - .setCornerRadius(layer, cornerRadius) - .setCrop_legacy(layer, Rect(0, 0, size, size)) - .apply(); - { - const uint8_t bottom = size - 1; - const uint8_t right = size - 1; - auto shot = getScreenCapture(); - // Transparent corners - shot->expectColor(Rect(0, 0, testArea, testArea), Color::BLACK); - shot->expectColor(Rect(size - testArea, 0, right, testArea), Color::BLACK); - shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK); - shot->expectColor(Rect(size - testArea, bottom - testArea, right, bottom), Color::BLACK); - } -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetCornerRadiusChildCrop) { - sp<SurfaceControl> parent; - sp<SurfaceControl> child; - const uint8_t size = 64; - const uint8_t testArea = 4; - const float cornerRadius = 20.0f; - ASSERT_NO_FATAL_FAILURE(parent = createLayer("parent", size, size)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(parent, Color::RED, size, size)); - ASSERT_NO_FATAL_FAILURE(child = createLayer("child", size, size / 2)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(child, Color::GREEN, size, size / 2)); - - Transaction() - .setCornerRadius(parent, cornerRadius) - .setCrop_legacy(parent, Rect(0, 0, size, size)) - .reparent(child, parent->getHandle()) - .setPosition(child, 0, size / 2) - .apply(); - { - const uint8_t bottom = size - 1; - const uint8_t right = size - 1; - auto shot = getScreenCapture(); - // Top edge of child should not have rounded corners because it's translated in the parent - shot->expectColor(Rect(0, size / 2, right, static_cast<int>(bottom - cornerRadius)), - Color::GREEN); - // But bottom edges should have been clipped according to parent bounds - shot->expectColor(Rect(0, bottom - testArea, testArea, bottom), Color::BLACK); - shot->expectColor(Rect(right - testArea, bottom - testArea, right, bottom), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorBasic) { - sp<SurfaceControl> bufferLayer; - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(colorLayer = - createLayer("test", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor)); - - Transaction() - .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) - .setLayer(colorLayer, mLayerZBase + 1) - .apply(); - - { - SCOPED_TRACE("default color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } - - const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); - const Color expected = {15, 51, 85, 255}; - // this is handwavy, but the precison loss scaled by 255 (8-bit per - // channel) should be less than one - const uint8_t tolerance = 1; - Transaction().setColor(colorLayer, color).apply(); - { - SCOPED_TRACE("new color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expected, tolerance); - } -} - -// RED: Color layer base color and BufferQueueLayer/BufferStateLayer fill -// BLUE: prior background color -// GREEN: final background color -// BLACK: no color or fill -void LayerRenderTypeTransactionTest::setBackgroundColorHelper(uint32_t layerType, bool priorColor, - bool bufferFill, float alpha, - Color finalColor) { - sp<SurfaceControl> layer; - int32_t width = 500; - int32_t height = 500; - - Color fillColor = Color::RED; - Color priorBgColor = Color::BLUE; - Color expectedColor = Color::BLACK; - switch (layerType) { - case ISurfaceComposerClient::eFXSurfaceColor: - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 0, 0, layerType)); - Transaction() - .setCrop_legacy(layer, Rect(0, 0, width, height)) - .setColor(layer, half3(1.0f, 0, 0)) - .apply(); - expectedColor = fillColor; - break; - case ISurfaceComposerClient::eFXSurfaceBufferQueue: - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height)); - if (bufferFill) { - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, fillColor, width, height)); - expectedColor = fillColor; - } - Transaction().setCrop_legacy(layer, Rect(0, 0, width, height)).apply(); - break; - case ISurfaceComposerClient::eFXSurfaceBufferState: - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height, layerType)); - if (bufferFill) { - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, fillColor, width, height)); - expectedColor = fillColor; - } - Transaction().setFrame(layer, Rect(0, 0, width, height)).apply(); - break; - default: - GTEST_FAIL() << "Unknown layer type in setBackgroundColorHelper"; - return; - } - - if (priorColor && layerType != ISurfaceComposerClient::eFXSurfaceColor) { - Transaction() - .setBackgroundColor(layer, half3(0, 0, 1.0f), 1.0f, ui::Dataspace::UNKNOWN) - .apply(); - if (!bufferFill) { - expectedColor = priorBgColor; - } - } - - { - SCOPED_TRACE("default before setting background color layer"); - screenshot()->expectColor(Rect(0, 0, width, height), expectedColor); - } - Transaction() - .setBackgroundColor(layer, half3(0, 1.0f, 0), alpha, ui::Dataspace::UNKNOWN) - .apply(); - - { - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, width, height), finalColor); - shot->expectBorder(Rect(0, 0, width, height), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_Color_NoEffect) { - bool priorColor = false; - bool bufferFill = false; - float alpha = 1.0f; - Color finalColor = Color::RED; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceColor, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferQueue_BufferFill_NoPriorColor_Basic) { - bool priorColor = false; - bool bufferFill = true; - float alpha = 1.0f; - Color finalColor = Color::RED; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferQueue_NoBufferFill_NoPriorColor_Basic) { - bool priorColor = false; - bool bufferFill = false; - float alpha = 1.0f; - Color finalColor = Color::GREEN; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, SetBackgroundColor_BufferQueue_BufferFill_PriorColor_Basic) { - bool priorColor = true; - bool bufferFill = true; - float alpha = 1.0f; - Color finalColor = Color::RED; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferQueue_NoBufferFill_PriorColor_Basic) { - bool priorColor = true; - bool bufferFill = false; - float alpha = 1.0f; - Color finalColor = Color::GREEN; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, - priorColor, bufferFill, alpha, finalColor)); -} -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferQueue_NoPriorColor_ZeroAlpha_NoEffect) { - bool priorColor = false; - bool bufferFill = false; - float alpha = 0; - Color finalColor = Color::BLACK; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferQueue_PriorColor_ZeroAlpha_DeleteBackground) { - bool priorColor = true; - bool bufferFill = false; - float alpha = 0; - Color finalColor = Color::BLACK; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferQueue, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferState_BufferFill_NoPriorColor_Basic) { - bool priorColor = false; - bool bufferFill = true; - float alpha = 1.0f; - Color finalColor = Color::RED; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferState_NoBufferFill_NoPriorColor_Basic) { - bool priorColor = false; - bool bufferFill = false; - float alpha = 1.0f; - Color finalColor = Color::GREEN; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferState_NoBufferFill_PriorColor_Basic) { - bool priorColor = true; - bool bufferFill = false; - float alpha = 1.0f; - Color finalColor = Color::GREEN; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferState_NoPriorColor_ZeroAlpha_NoEffect) { - bool priorColor = false; - bool bufferFill = false; - float alpha = 0; - Color finalColor = Color::BLACK; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, - SetBackgroundColor_BufferState_PriorColor_ZeroAlpha_DeleteBackground) { - bool priorColor = true; - bool bufferFill = false; - float alpha = 0; - Color finalColor = Color::BLACK; - ASSERT_NO_FATAL_FAILURE(setBackgroundColorHelper(ISurfaceComposerClient::eFXSurfaceBufferState, - priorColor, bufferFill, alpha, finalColor)); -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorClamped) { - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(colorLayer = - createLayer("test", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor)); - Transaction() - .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) - .setColor(colorLayer, half3(2.0f, -1.0f, 0.0f)) - .apply(); - - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorWithAlpha) { - sp<SurfaceControl> bufferLayer; - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(colorLayer = - createLayer("test", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor)); - Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply(); - - const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); - const float alpha = 0.25f; - const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f); - // this is handwavy, but the precison loss scaled by 255 (8-bit per - // channel) should be less than one - const uint8_t tolerance = 1; - Transaction() - .setColor(colorLayer, color) - .setAlpha(colorLayer, alpha) - .setLayer(colorLayer, mLayerZBase + 1) - .apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255}, - tolerance); -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorWithParentAlpha_Bug74220420) { - sp<SurfaceControl> bufferLayer; - sp<SurfaceControl> parentLayer; - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test bg", 32, 32)); - ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parentWithAlpha", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::RED, 32, 32)); - ASSERT_NO_FATAL_FAILURE(colorLayer = createLayer("childWithColor", 0 /* buffer width */, - 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor)); - Transaction().setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)).apply(); - const half3 color(15.0f / 255.0f, 51.0f / 255.0f, 85.0f / 255.0f); - const float alpha = 0.25f; - const ubyte3 expected((vec3(color) * alpha + vec3(1.0f, 0.0f, 0.0f) * (1.0f - alpha)) * 255.0f); - // this is handwavy, but the precision loss scaled by 255 (8-bit per - // channel) should be less than one - const uint8_t tolerance = 1; - Transaction() - .reparent(colorLayer, parentLayer->getHandle()) - .setColor(colorLayer, color) - .setAlpha(parentLayer, alpha) - .setLayer(parentLayer, mLayerZBase + 1) - .apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), {expected.r, expected.g, expected.b, 255}, - tolerance); -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetColorWithBuffer) { - sp<SurfaceControl> bufferLayer; - ASSERT_NO_FATAL_FAILURE(bufferLayer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(bufferLayer, Color::RED, 32, 32)); - - // color is ignored - Transaction().setColor(bufferLayer, half3(0.0f, 1.0f, 0.0f)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); -} - -TEST_P(LayerTypeAndRenderTypeTransactionTest, SetLayerStackBasic) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED, 32, 32)); - - Transaction().setLayerStack(layer, mDisplayLayerStack + 1).apply(); - { - SCOPED_TRACE("non-existing layer stack"); - getScreenCapture()->expectColor(mDisplayRect, Color::BLACK); - } - - Transaction().setLayerStack(layer, mDisplayLayerStack).apply(); - { - SCOPED_TRACE("original layer stack"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 0, 0).apply(); - { - SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); - } - - Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).setPosition(layer, 32, 0).apply(); - { - SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, - Color::WHITE, Color::BLUE); - } - - Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).setPosition(layer, 0, 32).apply(); - { - SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, - Color::RED, Color::GREEN); - } - - Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).setPosition(layer, 32, 0).apply(); - { - SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, - Color::WHITE, Color::GREEN); - } - - Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setPosition(layer, 0, 0).apply(); - { - SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 64), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE, true /* filtered */); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetMatrixBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - Transaction() - .setMatrix(layer, 1.0f, 0.0f, 0.0f, 1.0f) - .setFrame(layer, Rect(0, 0, 32, 32)) - .apply(); - { - SCOPED_TRACE("IDENTITY"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); - } - - Transaction().setMatrix(layer, -1.0f, 0.0f, 0.0f, 1.0f).apply(); - { - SCOPED_TRACE("FLIP_H"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); - } - - Transaction().setMatrix(layer, 1.0f, 0.0f, 0.0f, -1.0f).apply(); - { - SCOPED_TRACE("FLIP_V"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); - } - - Transaction().setMatrix(layer, 0.0f, 1.0f, -1.0f, 0.0f).apply(); - { - SCOPED_TRACE("ROT_90"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); - } - - Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).apply(); - { - SCOPED_TRACE("SCALE"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetMatrixRot45_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - const float rot = M_SQRT1_2; // 45 degrees - const float trans = M_SQRT2 * 16.0f; - Transaction().setMatrix(layer, rot, rot, -rot, rot).setPosition(layer, trans, 0).apply(); - - auto shot = getScreenCapture(); - // check a 8x8 region inside each color - auto get8x8Rect = [](int32_t centerX, int32_t centerY) { - const int32_t halfL = 4; - return Rect(centerX - halfL, centerY - halfL, centerX + halfL, centerY + halfL); - }; - const int32_t unit = int32_t(trans / 2); - shot->expectColor(get8x8Rect(2 * unit, 1 * unit), Color::RED); - shot->expectColor(get8x8Rect(3 * unit, 2 * unit), Color::GREEN); - shot->expectColor(get8x8Rect(1 * unit, 2 * unit), Color::BLUE); - shot->expectColor(get8x8Rect(2 * unit, 3 * unit), Color::WHITE); -} - -TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithResize_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setMatrix is applied after any pending resize, unlike setPosition - Transaction().setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f).setSize(layer, 64, 64).apply(); - { - SCOPED_TRACE("resize pending"); - auto shot = getScreenCapture(); - const Rect rect(0, 0, 32, 32); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("resize applied"); - const Rect rect(0, 0, 128, 128); - getScreenCapture()->expectColor(rect, Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetMatrixWithScaleToWindow_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setMatrix is immediate with SCALE_TO_WINDOW, unlike setPosition - Transaction() - .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setSize(layer, 64, 64) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .apply(); - getScreenCapture()->expectColor(Rect(0, 0, 128, 128), Color::RED); -} - -TEST_P(LayerRenderTypeTransactionTest, SetOverrideScalingModeBasic_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - // XXX SCALE_CROP is not respected; calling setSize and - // setOverrideScalingMode in separate transactions does not work - // (b/69315456) - Transaction() - .setSize(layer, 64, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .apply(); - { - SCOPED_TRACE("SCALE_TO_WINDOW"); - getScreenCapture()->expectQuadrant(Rect(0, 0, 64, 16), Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE, true /* filtered */); - } -} - -TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - - sp<IBinder> handle = layer->getHandle(); - ASSERT_TRUE(handle != nullptr); - - FrameStats frameStats; - mClient->getLayerFrameStats(handle, &frameStats); - - ASSERT_GT(frameStats.refreshPeriodNano, static_cast<nsecs_t>(0)); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - const Rect crop(8, 8, 24, 24); - - Transaction().setCrop_legacy(layer, crop).apply(); - auto shot = getScreenCapture(); - shot->expectColor(crop, Color::RED); - shot->expectBorder(crop, Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - const Rect crop(8, 8, 24, 24); - - Transaction().setCrop(layer, crop).apply(); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - { - SCOPED_TRACE("empty rect"); - Transaction().setCrop_legacy(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - { - SCOPED_TRACE("negative rect"); - Transaction().setCrop_legacy(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropEmpty_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - { - SCOPED_TRACE("empty rect"); - Transaction().setCrop(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - } - - { - SCOPED_TRACE("negative rect"); - Transaction().setCrop(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - Transaction().setCrop_legacy(layer, Rect(-128, -64, 128, 64)).apply(); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::RED); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 64, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); - - Transaction().setFrame(layer, Rect(0, 0, 64, 64)).apply(); - - Transaction().setBuffer(layer, buffer).apply(); - - // Partially out of bounds in the negative (upper left) direction - Transaction().setCrop(layer, Rect(-128, -128, 32, 16)).apply(); - { - SCOPED_TRACE("out of bounds, negative (upper left) direction"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::BLUE); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); - } - - // Partially out of bounds in the positive (lower right) direction - Transaction().setCrop(layer, Rect(0, 16, 128, 128)).apply(); - { - SCOPED_TRACE("out of bounds, positive (lower right) direction"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); - } - - // Fully out of buffer space bounds - Transaction().setCrop(layer, Rect(-128, -128, -1, -1)).apply(); - { - SCOPED_TRACE("Fully out of bounds"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 16), Color::BLUE); - shot->expectColor(Rect(0, 16, 64, 64), Color::RED); - shot->expectBorder(Rect(0, 0, 64, 64), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - const Point position(32, 32); - const Rect crop(8, 8, 24, 24); - Transaction().setPosition(layer, position.x, position.y).setCrop_legacy(layer, crop).apply(); - auto shot = getScreenCapture(); - shot->expectColor(crop + position, Color::RED); - shot->expectBorder(crop + position, Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropWithTranslation_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - const Rect frame(32, 32, 64, 64); - const Rect crop(8, 8, 24, 24); - Transaction().setFrame(layer, frame).setCrop(layer, crop).apply(); - auto shot = getScreenCapture(); - shot->expectColor(frame, Color::RED); - shot->expectBorder(frame, Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropWithScale_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // crop_legacy is affected by matrix - Transaction() - .setMatrix(layer, 2.0f, 0.0f, 0.0f, 2.0f) - .setCrop_legacy(layer, Rect(8, 8, 24, 24)) - .apply(); - auto shot = getScreenCapture(); - shot->expectColor(Rect(16, 16, 48, 48), Color::RED); - shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropWithResize_BufferQueue) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setCrop_legacy is applied immediately by default, with or without resize pending - Transaction().setCrop_legacy(layer, Rect(8, 8, 24, 24)).setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(8, 8, 24, 24), Color::RED); - shot->expectBorder(Rect(8, 8, 24, 24), Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("resize applied"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(8, 8, 16, 16), Color::RED); - shot->expectBorder(Rect(8, 8, 16, 16), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - const Rect frame(8, 8, 24, 24); - - Transaction().setFrame(layer, frame).apply(); - auto shot = getScreenCapture(); - shot->expectColor(frame, Color::RED); - shot->expectBorder(frame, Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameEmpty_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - { - SCOPED_TRACE("empty rect"); - Transaction().setFrame(layer, Rect(8, 8, 8, 8)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } - - { - SCOPED_TRACE("negative rect"); - Transaction().setFrame(layer, Rect(8, 8, 0, 0)).apply(); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultParentless_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 10, 10)); - - // A parentless layer will default to a frame with the same size as the buffer - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBSParent_BufferState) { - sp<SurfaceControl> parent, child; - ASSERT_NO_FATAL_FAILURE( - parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); - - ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - - Transaction().reparent(child, parent->getHandle()).apply(); - - // A layer will default to the frame of its parent - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameDefaultBQParent_BufferState) { - sp<SurfaceControl> parent, child; - ASSERT_NO_FATAL_FAILURE(parent = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(parent, Color::RED, 32, 32)); - - ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - - Transaction().reparent(child, parent->getHandle()).apply(); - - // A layer will default to the frame of its parent - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameUpdate_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - Transaction().setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - std::this_thread::sleep_for(500ms); - - Transaction().setFrame(layer, Rect(16, 16, 48, 48)).apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(16, 16, 48, 48), Color::RED); - shot->expectBorder(Rect(16, 16, 48, 48), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFrameOutsideBounds_BufferState) { - sp<SurfaceControl> parent, child; - ASSERT_NO_FATAL_FAILURE( - parent = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE( - child = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - Transaction().reparent(child, parent->getHandle()).apply(); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(parent, Color::RED, 32, 32)); - Transaction().setFrame(parent, Rect(0, 0, 32, 32)).apply(); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::BLUE, 10, 10)); - Transaction().setFrame(child, Rect(0, 16, 32, 32)).apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 16), Color::RED); - shot->expectColor(Rect(0, 16, 32, 32), Color::BLUE); - shot->expectBorder(Rect(0, 0, 32, 32), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetBufferBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleBuffers_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - { - SCOPED_TRACE("set buffer 1"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32)); - - { - SCOPED_TRACE("set buffer 2"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLUE); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32)); - - { - SCOPED_TRACE("set buffer 3"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetBufferMultipleLayers_BufferState) { - sp<SurfaceControl> layer1; - ASSERT_NO_FATAL_FAILURE( - layer1 = createLayer("test", 64, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<SurfaceControl> layer2; - ASSERT_NO_FATAL_FAILURE( - layer2 = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::RED, 64, 64)); - - Transaction().setFrame(layer1, Rect(0, 0, 64, 64)).apply(); - { - SCOPED_TRACE("set layer 1 buffer red"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 64, 64), Color::RED); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::BLUE, 32, 32)); - - Transaction().setFrame(layer2, Rect(0, 0, 32, 32)).apply(); - { - SCOPED_TRACE("set layer 2 buffer blue"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectColor(Rect(0, 32, 64, 64), Color::RED); - shot->expectColor(Rect(0, 32, 32, 64), Color::RED); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer1, Color::GREEN, 64, 64)); - { - SCOPED_TRACE("set layer 1 buffer green"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::BLUE); - shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); - shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer2, Color::WHITE, 32, 32)); - - { - SCOPED_TRACE("set layer 2 buffer white"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 32, 32), Color::WHITE); - shot->expectColor(Rect(0, 32, 64, 64), Color::GREEN); - shot->expectColor(Rect(0, 32, 32, 64), Color::GREEN); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN}; - - std::array<sp<GraphicBuffer>, 10> buffers; - - size_t idx = 0; - for (auto& buffer : buffers) { - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - Color color = colors[idx % colors.size()]; - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); - idx++; - } - - // Set each buffer twice. The first time adds it to the cache, the second time tests that the - // cache is working. - idx = 0; - for (auto& buffer : buffers) { - for (int i = 0; i < 2; i++) { - Transaction().setBuffer(layer, buffer).apply(); - - Color color = colors[idx % colors.size()]; - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); - } - idx++; - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN}; - - std::array<sp<GraphicBuffer>, 70> buffers; - - size_t idx = 0; - for (auto& buffer : buffers) { - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - Color color = colors[idx % colors.size()]; - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); - idx++; - } - - // Set each buffer twice. The first time adds it to the cache, the second time tests that the - // cache is working. - idx = 0; - for (auto& buffer : buffers) { - for (int i = 0; i < 2; i++) { - Transaction().setBuffer(layer, buffer).apply(); - - Color color = colors[idx % colors.size()]; - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); - } - idx++; - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - std::array<Color, 4> colors = {Color::RED, Color::BLUE, Color::WHITE, Color::GREEN}; - - std::array<sp<GraphicBuffer>, 65> buffers; - - size_t idx = 0; - for (auto& buffer : buffers) { - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - Color color = colors[idx % colors.size()]; - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); - idx++; - } - - // Set each buffer twice. The first time adds it to the cache, the second time tests that the - // cache is working. - idx = 0; - for (auto& buffer : buffers) { - for (int i = 0; i < 2; i++) { - Transaction().setBuffer(layer, buffer).apply(); - - Color color = colors[idx % colors.size()]; - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), color); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); - } - if (idx == 0) { - buffers[0].clear(); - } - idx++; - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransformRotate90_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) - .setTransform(layer, NATIVE_WINDOW_TRANSFORM_ROT_90) - .apply(); - - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::RED, Color::WHITE, - Color::GREEN, true /* filtered */); -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipH_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) - .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_H) - .apply(); - - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::GREEN, Color::RED, Color::WHITE, - Color::BLUE, true /* filtered */); -} - -TEST_P(LayerRenderTypeTransactionTest, SetTransformFlipV_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerQuadrant(layer, 32, 32, Color::RED, Color::GREEN, - Color::BLUE, Color::WHITE)); - - Transaction() - .setFrame(layer, Rect(0, 0, 32, 32)) - .setTransform(layer, NATIVE_WINDOW_TRANSFORM_FLIP_V) - .apply(); - - getScreenCapture()->expectQuadrant(Rect(0, 0, 32, 32), Color::BLUE, Color::WHITE, Color::RED, - Color::GREEN, true /* filtered */); -} - -TEST_F(LayerTransactionTest, SetTransformToDisplayInverse_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - Transaction().setTransformToDisplayInverse(layer, false).apply(); - - ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::GREEN, 32, 32)); - - Transaction().setTransformToDisplayInverse(layer, true).apply(); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFenceBasic_BufferState) { - sp<SurfaceControl> layer; - Transaction transaction; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - sp<Fence> fence; - if (getBuffer(nullptr, &fence) != NO_ERROR) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - Transaction().setBuffer(layer, buffer).setAcquireFence(layer, fence).apply(); - - status_t status = fence->wait(1000); - ASSERT_NE(static_cast<status_t>(Fence::Status::Unsignaled), status); - std::this_thread::sleep_for(200ms); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - sp<Fence> fence = Fence::NO_FENCE; - - Transaction() - .setBuffer(layer, buffer) - .setAcquireFence(layer, fence) - .apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - Transaction() - .setBuffer(layer, buffer) - .setDataspace(layer, ui::Dataspace::UNKNOWN) - .apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - HdrMetadata hdrMetadata; - hdrMetadata.validTypes = 0; - Transaction() - .setBuffer(layer, buffer) - .setHdrMetadata(layer, hdrMetadata) - .apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - Region region; - region.set(32, 32); - Transaction() - .setBuffer(layer, buffer) - .setSurfaceDamageRegion(layer, region) - .apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - sp<GraphicBuffer> buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); - TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); - - Transaction() - .setBuffer(layer, buffer) - .setApi(layer, NATIVE_WINDOW_API_CPU) - .apply(); - - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::RED); - shot->expectBorder(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::BLACK); -} - -TEST_F(LayerTransactionTest, SetSidebandStreamNull_BufferState) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE( - layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); - - // verify this doesn't cause a crash - Transaction().setSidebandStream(layer, nullptr).apply(); -} - -TEST_F(LayerTransactionTest, ReparentToSelf) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - Transaction().reparent(layer, layer->getHandle()).apply(); - - { - // We expect the transaction to be silently dropped, but for SurfaceFlinger - // to still be functioning. - SCOPED_TRACE("after reparent to self"); - const Rect rect(0, 0, 32, 32); - auto shot = screenshot(); - shot->expectColor(rect, Color::RED); - shot->expectBorder(rect, Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorTransformBasic) { - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(colorLayer = - createLayer("test", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor)); - Transaction() - .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) - .setLayer(colorLayer, mLayerZBase + 1) - .apply(); - { - SCOPED_TRACE("default color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } - - const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); - half3 expected = color; - mat3 matrix; - matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11; - matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11; - matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11; - - // degamma before applying the matrix - if (mColorManagementUsed) { - ColorTransformHelper::DegammaColor(expected); - } - - ColorTransformHelper::applyMatrix(expected, matrix); - - if (mColorManagementUsed) { - ColorTransformHelper::GammaColor(expected); - } - - const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255), - uint8_t(expected.b * 255), 255}; - - // this is handwavy, but the precison loss scaled by 255 (8-bit per - // channel) should be less than one - const uint8_t tolerance = 1; - - Transaction().setColor(colorLayer, color) - .setColorTransform(colorLayer, matrix, vec3()).apply(); - { - SCOPED_TRACE("new color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnParent) { - sp<SurfaceControl> parentLayer; - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */, - 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceContainer)); - ASSERT_NO_FATAL_FAILURE( - colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get())); - - Transaction() - .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100)) - .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) - .setLayer(parentLayer, mLayerZBase + 1) - .apply(); - { - SCOPED_TRACE("default color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } - - const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); - half3 expected = color; - mat3 matrix; - matrix[0][0] = 0.3; matrix[1][0] = 0.59; matrix[2][0] = 0.11; - matrix[0][1] = 0.3; matrix[1][1] = 0.59; matrix[2][1] = 0.11; - matrix[0][2] = 0.3; matrix[1][2] = 0.59; matrix[2][2] = 0.11; - - // degamma before applying the matrix - if (mColorManagementUsed) { - ColorTransformHelper::DegammaColor(expected); - } - - ColorTransformHelper::applyMatrix(expected, matrix); - - if (mColorManagementUsed) { - ColorTransformHelper::GammaColor(expected); - } - - const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255), - uint8_t(expected.b * 255), 255}; - - // this is handwavy, but the precison loss scaled by 255 (8-bit per - // channel) should be less than one - const uint8_t tolerance = 1; - - Transaction() - .setColor(colorLayer, color) - .setColorTransform(parentLayer, matrix, vec3()) - .apply(); - { - SCOPED_TRACE("new color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnChildAndParent) { - sp<SurfaceControl> parentLayer; - sp<SurfaceControl> colorLayer; - ASSERT_NO_FATAL_FAILURE(parentLayer = createLayer("parent", 0 /* buffer width */, - 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceContainer)); - ASSERT_NO_FATAL_FAILURE( - colorLayer = createLayer("test", 0 /* buffer width */, 0 /* buffer height */, - ISurfaceComposerClient::eFXSurfaceColor, parentLayer.get())); - - Transaction() - .setCrop_legacy(parentLayer, Rect(0, 0, 100, 100)) - .setCrop_legacy(colorLayer, Rect(0, 0, 32, 32)) - .setLayer(parentLayer, mLayerZBase + 1) - .apply(); - { - SCOPED_TRACE("default color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::BLACK); - } - - const half3 color(50.0f / 255.0f, 100.0f / 255.0f, 150.0f / 255.0f); - half3 expected = color; - mat3 matrixChild; - matrixChild[0][0] = 0.3; matrixChild[1][0] = 0.59; matrixChild[2][0] = 0.11; - matrixChild[0][1] = 0.3; matrixChild[1][1] = 0.59; matrixChild[2][1] = 0.11; - matrixChild[0][2] = 0.3; matrixChild[1][2] = 0.59; matrixChild[2][2] = 0.11; - mat3 matrixParent; - matrixParent[0][0] = 0.2; matrixParent[1][0] = 0.4; matrixParent[2][0] = 0.10; - matrixParent[0][1] = 0.2; matrixParent[1][1] = 0.4; matrixParent[2][1] = 0.10; - matrixParent[0][2] = 0.2; matrixParent[1][2] = 0.4; matrixParent[2][2] = 0.10; - - // degamma before applying the matrix - if (mColorManagementUsed) { - ColorTransformHelper::DegammaColor(expected); - } - - ColorTransformHelper::applyMatrix(expected, matrixChild); - ColorTransformHelper::applyMatrix(expected, matrixParent); - - if (mColorManagementUsed) { - ColorTransformHelper::GammaColor(expected); - } - - const Color expectedColor = {uint8_t(expected.r * 255), uint8_t(expected.g * 255), - uint8_t(expected.b * 255), 255}; - - // this is handwavy, but the precison loss scaled by 255 (8-bit per - // channel) should be less than one - const uint8_t tolerance = 1; - - Transaction() - .setColor(colorLayer, color) - .setColorTransform(parentLayer, matrixParent, vec3()) - .setColorTransform(colorLayer, matrixChild, vec3()) - .apply(); - { - SCOPED_TRACE("new color"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), expectedColor, tolerance); - } -} - -class LayerCallbackTest : public LayerTransactionTest { -public: - virtual sp<SurfaceControl> createBufferStateLayer() { - return createLayer(mClient, "test", 0, 0, ISurfaceComposerClient::eFXSurfaceBufferState); - } - - static int fillTransaction(Transaction& transaction, CallbackHelper* callbackHelper, - const sp<SurfaceControl>& layer = nullptr, bool setBuffer = true, - bool setBackgroundColor = false) { - if (layer) { - sp<GraphicBuffer> buffer; - sp<Fence> fence; - if (setBuffer) { - int err = getBuffer(&buffer, &fence); - if (err != NO_ERROR) { - return err; - } - - transaction.setBuffer(layer, buffer); - transaction.setAcquireFence(layer, fence); - } - - if (setBackgroundColor) { - transaction.setBackgroundColor(layer, /*color*/ half3(1.0f, 0, 0), /*alpha*/ 1.0f, - ui::Dataspace::UNKNOWN); - } - } - - transaction.addTransactionCompletedCallback(callbackHelper->function, - callbackHelper->getContext()); - return NO_ERROR; - } - - static void waitForCallback(CallbackHelper& helper, const ExpectedResult& expectedResult, - bool finalState = false) { - CallbackData callbackData; - ASSERT_NO_FATAL_FAILURE(helper.getCallbackData(&callbackData)); - EXPECT_NO_FATAL_FAILURE(expectedResult.verifyCallbackData(callbackData)); - - if (finalState) { - ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState()); - } - } - - static void waitForCallbacks(CallbackHelper& helper, - const std::vector<ExpectedResult>& expectedResults, - bool finalState = false) { - for (const auto& expectedResult : expectedResults) { - waitForCallback(helper, expectedResult); - } - if (finalState) { - ASSERT_NO_FATAL_FAILURE(helper.verifyFinalState()); - } - } -}; - -TEST_F(LayerCallbackTest, BufferColor) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer, true, true); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, NoBufferNoColor) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer, false, false); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, - ExpectedResult::Buffer::NOT_ACQUIRED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, BufferNoColor) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer, true, false); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, NoBufferColor) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer, false, true); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::NOT_ACQUIRED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, NoStateChange) { - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.apply(); - - ExpectedResult expected; - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, OffScreen) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.setFrame(layer, Rect(-100, -100, 100, 100)).apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, MergeBufferNoColor) { - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); - ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - -TEST_F(LayerCallbackTest, MergeNoBufferColor) { - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); - ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - int err = fillTransaction(transaction1, &callback1, layer1, false, true); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2, false, true); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, - ExpectedResult::Buffer::NOT_ACQUIRED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - -TEST_F(LayerCallbackTest, MergeOneBufferOneColor) { - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); - ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2, false, true); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer1); - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer2, - ExpectedResult::Buffer::NOT_ACQUIRED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} -TEST_F(LayerCallbackTest, Merge_SameCallback) { - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); - ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback; - int err = fillTransaction(transaction1, &callback, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction2.merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, Merge_SameLayer) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - int err = fillTransaction(transaction1, &callback1, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction2.merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - -TEST_F(LayerCallbackTest, Merge_DifferentClients) { - sp<SurfaceComposerClient> client1(new SurfaceComposerClient), - client2(new SurfaceComposerClient); - - ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; - ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; - - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - -TEST_F(LayerCallbackTest, MultipleTransactions) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - for (size_t i = 0; i < 10; i++) { - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::ACQUIRED, - (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED - : ExpectedResult::PreviousBuffer::RELEASED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); - } - ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_NoStateChange) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - for (size_t i = 0; i < 10; i++) { - ExpectedResult expected; - - if (i == 0) { - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - } else { - int err = fillTransaction(transaction, &callback); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - } - - transaction.apply(); - - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected)); - } - ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_SameStateChange) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - for (size_t i = 0; i < 10; i++) { - if (i == 0) { - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - } else { - int err = fillTransaction(transaction, &callback); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - } - - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - ExpectedResult expected; - expected.addSurface((i == 0) ? ExpectedResult::Transaction::PRESENTED - : ExpectedResult::Transaction::NOT_PRESENTED, - layer, - (i == 0) ? ExpectedResult::Buffer::ACQUIRED - : ExpectedResult::Buffer::NOT_ACQUIRED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, i == 0)); - } - ASSERT_NO_FATAL_FAILURE(callback.verifyFinalState()); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_Merge) { - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createBufferStateLayer()); - ASSERT_NO_FATAL_FAILURE(layer2 = createBufferStateLayer()); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - for (size_t i = 0; i < 10; i++) { - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, - ExpectedResult::Buffer::ACQUIRED, - (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED - : ExpectedResult::PreviousBuffer::RELEASED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected)); - } - ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState()); - ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState()); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients) { - sp<SurfaceComposerClient> client1(new SurfaceComposerClient), - client2(new SurfaceComposerClient); - ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; - ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; - - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - for (size_t i = 0; i < 10; i++) { - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}, - ExpectedResult::Buffer::ACQUIRED, - (i == 0) ? ExpectedResult::PreviousBuffer::NOT_RELEASED - : ExpectedResult::PreviousBuffer::RELEASED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected)); - } - ASSERT_NO_FATAL_FAILURE(callback1.verifyFinalState()); - ASSERT_NO_FATAL_FAILURE(callback2.verifyFinalState()); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_NoStateChange) { - sp<SurfaceComposerClient> client1(new SurfaceComposerClient), - client2(new SurfaceComposerClient); - ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; - ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; - - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - - // Normal call to set up test - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); - expected.reset(); - - // Test - err = fillTransaction(transaction1, &callback1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction2.merge(std::move(transaction1)).apply(); - - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_Merge_DifferentClients_SameStateChange) { - sp<SurfaceComposerClient> client1(new SurfaceComposerClient), - client2(new SurfaceComposerClient); - - ASSERT_EQ(NO_ERROR, client1->initCheck()) << "failed to create SurfaceComposerClient"; - ASSERT_EQ(NO_ERROR, client2->initCheck()) << "failed to create SurfaceComposerClient"; - - sp<SurfaceControl> layer1, layer2; - ASSERT_NO_FATAL_FAILURE(layer1 = createLayer(client1, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - ASSERT_NO_FATAL_FAILURE(layer2 = createLayer(client2, "test", 0, 0, - ISurfaceComposerClient::eFXSurfaceBufferState)); - - Transaction transaction1, transaction2; - CallbackHelper callback1, callback2; - - // Normal call to set up test - int err = fillTransaction(transaction1, &callback1, layer1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2, layer2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction1.setFrame(layer1, Rect(0, 0, 32, 32)); - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - ExpectedResult expected; - expected.addSurfaces(ExpectedResult::Transaction::PRESENTED, {layer1, layer2}); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); - expected.reset(); - - // Test - err = fillTransaction(transaction1, &callback1); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - err = fillTransaction(transaction2, &callback2); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction2.setFrame(layer2, Rect(32, 32, 64, 64)).merge(std::move(transaction1)).apply(); - - expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer2, - ExpectedResult::Buffer::NOT_ACQUIRED); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected, true)); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - std::vector<ExpectedResult> expectedResults(50); - for (auto& expected : expectedResults) { - expected.reset(); - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::ACQUIRED, - ExpectedResult::PreviousBuffer::UNKNOWN); - - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.apply(); - } - EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_NoStateChange) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - // Normal call to set up test - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); - - // Test - std::vector<ExpectedResult> expectedResults(50); - for (auto& expected : expectedResults) { - expected.reset(); - - err = fillTransaction(transaction, &callback); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.apply(); - } - EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); -} - -TEST_F(LayerCallbackTest, MultipleTransactions_SingleFrame_SameStateChange) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - // Normal call to set up test - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - - ExpectedResult expectedResult; - expectedResult.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expectedResult, true)); - - // Test - std::vector<ExpectedResult> expectedResults(50); - for (auto& expected : expectedResults) { - expected.reset(); - expected.addSurface(ExpectedResult::Transaction::NOT_PRESENTED, layer, - ExpectedResult::Buffer::NOT_ACQUIRED); - - err = fillTransaction(transaction, &callback); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - transaction.setFrame(layer, Rect(0, 0, 32, 32)).apply(); - } - EXPECT_NO_FATAL_FAILURE(waitForCallbacks(callback, expectedResults, true)); -} - -TEST_F(LayerCallbackTest, DesiredPresentTime) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - // Try to present 100ms in the future - nsecs_t time = systemTime() + (100 * 1e6); - - transaction.setDesiredPresentTime(time); - transaction.apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - expected.addExpectedPresentTime(time); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -TEST_F(LayerCallbackTest, DesiredPresentTime_Multiple) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback1; - int err = fillTransaction(transaction, &callback1, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - // Try to present 100ms in the future - nsecs_t time = systemTime() + (100 * 1e6); - - transaction.setDesiredPresentTime(time); - transaction.apply(); - - ExpectedResult expected1; - expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - expected1.addExpectedPresentTime(time); - - CallbackHelper callback2; - err = fillTransaction(transaction, &callback2, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - // Try to present 33ms after the first frame - time += (33.3 * 1e6); - - transaction.setDesiredPresentTime(time); - transaction.apply(); - - ExpectedResult expected2; - expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::ACQUIRED, - ExpectedResult::PreviousBuffer::RELEASED); - expected2.addExpectedPresentTime(time); - - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true)); -} - -TEST_F(LayerCallbackTest, DesiredPresentTime_OutOfOrder) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback1; - int err = fillTransaction(transaction, &callback1, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - // Try to present 100ms in the future - nsecs_t time = systemTime() + (100 * 1e6); - - transaction.setDesiredPresentTime(time); - transaction.apply(); - - ExpectedResult expected1; - expected1.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - expected1.addExpectedPresentTime(time); - - CallbackHelper callback2; - err = fillTransaction(transaction, &callback2, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - // Try to present 33ms before the previous frame - time -= (33.3 * 1e6); - - transaction.setDesiredPresentTime(time); - transaction.apply(); - - ExpectedResult expected2; - expected2.addSurface(ExpectedResult::Transaction::PRESENTED, layer, - ExpectedResult::Buffer::ACQUIRED, - ExpectedResult::PreviousBuffer::RELEASED); - - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback1, expected1, true)); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback2, expected2, true)); -} - -TEST_F(LayerCallbackTest, DesiredPresentTime_Past) { - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createBufferStateLayer()); - - Transaction transaction; - CallbackHelper callback; - int err = fillTransaction(transaction, &callback, layer); - if (err) { - GTEST_SUCCEED() << "test not supported"; - return; - } - - // Try to present 100ms in the past - nsecs_t time = systemTime() - (100 * 1e6); - - transaction.setDesiredPresentTime(time); - transaction.apply(); - - ExpectedResult expected; - expected.addSurface(ExpectedResult::Transaction::PRESENTED, layer); - expected.addExpectedPresentTime(systemTime()); - EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); -} - -class LayerUpdateTest : public LayerTransactionTest { -protected: - virtual void SetUp() { - LayerTransactionTest::SetUp(); - ASSERT_EQ(NO_ERROR, mClient->initCheck()); - - const auto display = SurfaceComposerClient::getInternalDisplayToken(); - ASSERT_FALSE(display == nullptr); - - DisplayInfo info; - ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getDisplayInfo(display, &info)); - - ssize_t displayWidth = info.w; - ssize_t displayHeight = info.h; - - // Background surface - mBGSurfaceControl = createLayer(String8("BG Test Surface"), displayWidth, - displayHeight, 0); - ASSERT_TRUE(mBGSurfaceControl != nullptr); - ASSERT_TRUE(mBGSurfaceControl->isValid()); - TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 63, 63, 195); - - // Foreground surface - mFGSurfaceControl = createLayer(String8("FG Test Surface"), 64, 64, 0); - - ASSERT_TRUE(mFGSurfaceControl != nullptr); - ASSERT_TRUE(mFGSurfaceControl->isValid()); - - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); - - // Synchronization surface - mSyncSurfaceControl = createLayer(String8("Sync Test Surface"), 1, 1, 0); - ASSERT_TRUE(mSyncSurfaceControl != nullptr); - ASSERT_TRUE(mSyncSurfaceControl->isValid()); - - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - - asTransaction([&](Transaction& t) { - t.setDisplayLayerStack(display, 0); - - t.setLayer(mBGSurfaceControl, INT32_MAX - 2).show(mBGSurfaceControl); - - t.setLayer(mFGSurfaceControl, INT32_MAX - 1) - .setPosition(mFGSurfaceControl, 64, 64) - .show(mFGSurfaceControl); - - t.setLayer(mSyncSurfaceControl, INT32_MAX - 1) - .setPosition(mSyncSurfaceControl, displayWidth - 2, displayHeight - 2) - .show(mSyncSurfaceControl); - }); - } - - virtual void TearDown() { - LayerTransactionTest::TearDown(); - mBGSurfaceControl = 0; - mFGSurfaceControl = 0; - mSyncSurfaceControl = 0; - } - - void waitForPostedBuffers() { - // Since the sync surface is in synchronous mode (i.e. double buffered) - // posting three buffers to it should ensure that at least two - // SurfaceFlinger::handlePageFlip calls have been made, which should - // guaranteed that a buffer posted to another Surface has been retired. - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - } - - - sp<SurfaceControl> mBGSurfaceControl; - sp<SurfaceControl> mFGSurfaceControl; - - // This surface is used to ensure that the buffers posted to - // mFGSurfaceControl have been picked up by SurfaceFlinger. - sp<SurfaceControl> mSyncSurfaceControl; -}; - -TEST_F(LayerUpdateTest, RelativesAreNotDetached) { - - std::unique_ptr<ScreenCapture> sc; - - sp<SurfaceControl> relative = createLayer(String8("relativeTestSurface"), 10, 10, 0); - TransactionUtils::fillSurfaceRGBA8(relative, 10, 10, 10); - waitForPostedBuffers(); - - Transaction{} - .setRelativeLayer(relative, mFGSurfaceControl->getHandle(), 1) - .setPosition(relative, 64, 64) - .apply(); - - { - // The relative should be on top of the FG control. - ScreenCapture::captureScreen(&sc); - sc->checkPixel(64, 64, 10, 10, 10); - } - Transaction{}.detachChildren(mFGSurfaceControl).apply(); - - { - // Nothing should change at this point. - ScreenCapture::captureScreen(&sc); - sc->checkPixel(64, 64, 10, 10, 10); - } - - Transaction{}.hide(relative).apply(); - - { - // Ensure that the relative was actually hidden, rather than - // being left in the detached but visible state. - ScreenCapture::captureScreen(&sc); - sc->expectFGColor(64, 64); - } -} - -class GeometryLatchingTest : public LayerUpdateTest { -protected: - void EXPECT_INITIAL_STATE(const char* trace) { - SCOPED_TRACE(trace); - ScreenCapture::captureScreen(&sc); - // We find the leading edge of the FG surface. - sc->expectFGColor(127, 127); - sc->expectBGColor(128, 128); - } - - void lockAndFillFGBuffer() { - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63, false); - } - - void unlockFGBuffer() { - sp<Surface> s = mFGSurfaceControl->getSurface(); - ASSERT_EQ(NO_ERROR, s->unlockAndPost()); - waitForPostedBuffers(); - } - - void completeFGResize() { - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); - waitForPostedBuffers(); - } - void restoreInitialState() { - asTransaction([&](Transaction& t) { - t.setSize(mFGSurfaceControl, 64, 64); - t.setPosition(mFGSurfaceControl, 64, 64); - t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 64, 64)); - }); - - EXPECT_INITIAL_STATE("After restoring initial state"); - } - std::unique_ptr<ScreenCapture> sc; -}; - -class CropLatchingTest : public GeometryLatchingTest { -protected: - void EXPECT_CROPPED_STATE(const char* trace) { - SCOPED_TRACE(trace); - ScreenCapture::captureScreen(&sc); - // The edge should be moved back one pixel by our crop. - sc->expectFGColor(126, 126); - sc->expectBGColor(127, 127); - sc->expectBGColor(128, 128); - } - - void EXPECT_RESIZE_STATE(const char* trace) { - SCOPED_TRACE(trace); - ScreenCapture::captureScreen(&sc); - // The FG is now resized too 128,128 at 64,64 - sc->expectFGColor(64, 64); - sc->expectFGColor(191, 191); - sc->expectBGColor(192, 192); - } -}; - -TEST_F(LayerUpdateTest, DeferredTransactionTest) { - std::unique_ptr<ScreenCapture> sc; - { - SCOPED_TRACE("before anything"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->expectFGColor(96, 96); - sc->expectBGColor(160, 160); - } - - // set up two deferred transactions on different frames - asTransaction([&](Transaction& t) { - t.setAlpha(mFGSurfaceControl, 0.75); - t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber()); - }); - - asTransaction([&](Transaction& t) { - t.setPosition(mFGSurfaceControl, 128, 128); - t.deferTransactionUntil_legacy(mFGSurfaceControl, mSyncSurfaceControl->getHandle(), - mSyncSurfaceControl->getSurface()->getNextFrameNumber() + 1); - }); - - { - SCOPED_TRACE("before any trigger"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->expectFGColor(96, 96); - sc->expectBGColor(160, 160); - } - - // should trigger the first deferred transaction, but not the second one - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - { - SCOPED_TRACE("after first trigger"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->checkPixel(96, 96, 162, 63, 96); - sc->expectBGColor(160, 160); - } - - // should show up immediately since it's not deferred - asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 1.0); }); - - // trigger the second deferred transaction - TransactionUtils::fillSurfaceRGBA8(mSyncSurfaceControl, 31, 31, 31); - { - SCOPED_TRACE("after second trigger"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(32, 32); - sc->expectBGColor(96, 96); - sc->expectFGColor(160, 160); - } -} - -TEST_F(LayerUpdateTest, LayerWithNoBuffersResizesImmediately) { - std::unique_ptr<ScreenCapture> sc; - - sp<SurfaceControl> childNoBuffer = - createSurface(mClient, "Bufferless child", 0 /* buffer width */, 0 /* buffer height */, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - sp<SurfaceControl> childBuffer = createSurface(mClient, "Buffered child", 20, 20, - PIXEL_FORMAT_RGBA_8888, 0, childNoBuffer.get()); - TransactionUtils::fillSurfaceRGBA8(childBuffer, 200, 200, 200); - SurfaceComposerClient::Transaction{} - .setCrop_legacy(childNoBuffer, Rect(0, 0, 10, 10)) - .show(childNoBuffer) - .show(childBuffer) - .apply(true); - { - ScreenCapture::captureScreen(&sc); - sc->expectChildColor(73, 73); - sc->expectFGColor(74, 74); - } - SurfaceComposerClient::Transaction{} - .setCrop_legacy(childNoBuffer, Rect(0, 0, 20, 20)) - .apply(true); - { - ScreenCapture::captureScreen(&sc); - sc->expectChildColor(73, 73); - sc->expectChildColor(74, 74); - } -} - -TEST_F(LayerUpdateTest, MergingTransactions) { - std::unique_ptr<ScreenCapture> sc; - { - SCOPED_TRACE("before move"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(0, 12); - sc->expectFGColor(75, 75); - sc->expectBGColor(145, 145); - } - - Transaction t1, t2; - t1.setPosition(mFGSurfaceControl, 128, 128); - t2.setPosition(mFGSurfaceControl, 0, 0); - // We expect that the position update from t2 now - // overwrites the position update from t1. - t1.merge(std::move(t2)); - t1.apply(); - - { - ScreenCapture::captureScreen(&sc); - sc->expectFGColor(1, 1); - } -} - -TEST_F(LayerUpdateTest, MergingTransactionFlags) { - Transaction().hide(mFGSurfaceControl).apply(); - std::unique_ptr<ScreenCapture> sc; - { - SCOPED_TRACE("before merge"); - ScreenCapture::captureScreen(&sc); - sc->expectBGColor(0, 12); - sc->expectBGColor(75, 75); - sc->expectBGColor(145, 145); - } - - Transaction t1, t2; - t1.show(mFGSurfaceControl); - t2.setFlags(mFGSurfaceControl, 0 /* flags */, layer_state_t::eLayerSecure /* mask */); - t1.merge(std::move(t2)); - t1.apply(); - - { - SCOPED_TRACE("after merge"); - ScreenCapture::captureScreen(&sc); - sc->expectFGColor(75, 75); - } -} - -class ChildLayerTest : public LayerUpdateTest { -protected: - void SetUp() override { - LayerUpdateTest::SetUp(); - mChild = createSurface(mClient, "Child surface", 10, 15, PIXEL_FORMAT_RGBA_8888, 0, - mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); - - { - SCOPED_TRACE("before anything"); - mCapture = screenshot(); - mCapture->expectChildColor(64, 64); - } - } - void TearDown() override { - LayerUpdateTest::TearDown(); - mChild = 0; - } - - sp<SurfaceControl> mChild; - std::unique_ptr<ScreenCapture> mCapture; -}; - -TEST_F(ChildLayerTest, ChildLayerPositioning) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); }); - - { - mCapture = screenshot(); - // Top left of foreground should now be at 0, 0 - mCapture->expectFGColor(0, 0); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(10, 10); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(20, 20); - } -} - -TEST_F(ChildLayerTest, ChildLayerCropping) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - t.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 5, 5)); - }); - - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(4, 4); - mCapture->expectBGColor(5, 5); - } -} - -TEST_F(ChildLayerTest, ChildLayerConstraints) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mFGSurfaceControl, 0, 0); - t.setPosition(mChild, 63, 63); - }); - - { - mCapture = screenshot(); - mCapture->expectFGColor(0, 0); - // Last pixel in foreground should now be the child. - mCapture->expectChildColor(63, 63); - // But the child should be constrained and the next pixel - // must be the background - mCapture->expectBGColor(64, 64); - } -} - -TEST_F(ChildLayerTest, ChildLayerScaling) { - asTransaction([&](Transaction& t) { t.setPosition(mFGSurfaceControl, 0, 0); }); - - // Find the boundary between the parent and child - { - mCapture = screenshot(); - mCapture->expectChildColor(9, 9); - mCapture->expectFGColor(10, 10); - } - - asTransaction([&](Transaction& t) { t.setMatrix(mFGSurfaceControl, 2.0, 0, 0, 2.0); }); - - // The boundary should be twice as far from the origin now. - // The pixels from the last test should all be child now - { - mCapture = screenshot(); - mCapture->expectChildColor(9, 9); - mCapture->expectChildColor(10, 10); - mCapture->expectChildColor(19, 19); - mCapture->expectFGColor(20, 20); - } -} - -// A child with a scale transform should be cropped by its parent bounds. -TEST_F(ChildLayerTest, ChildLayerScalingCroppedByParent) { - asTransaction([&](Transaction& t) { - t.setPosition(mFGSurfaceControl, 0, 0); - t.setPosition(mChild, 0, 0); - }); - - // Find the boundary between the parent and child. - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(9, 9); - mCapture->expectFGColor(10, 10); - } - - asTransaction([&](Transaction& t) { t.setMatrix(mChild, 10.0, 0, 0, 10.0); }); - - // The child should fill its parent bounds and be cropped by it. - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(63, 63); - mCapture->expectBGColor(64, 64); - } -} - -TEST_F(ChildLayerTest, ChildLayerAlpha) { - TransactionUtils::fillSurfaceRGBA8(mBGSurfaceControl, 0, 0, 254); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 254, 0, 0); - TransactionUtils::fillSurfaceRGBA8(mChild, 0, 254, 0); - waitForPostedBuffers(); - - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - }); - - { - mCapture = screenshot(); - // Unblended child color - mCapture->checkPixel(0, 0, 0, 254, 0); - } - - asTransaction([&](Transaction& t) { t.setAlpha(mChild, 0.5); }); - - { - mCapture = screenshot(); - // Child and BG blended. - mCapture->checkPixel(0, 0, 127, 127, 0); - } - - asTransaction([&](Transaction& t) { t.setAlpha(mFGSurfaceControl, 0.5); }); - - { - mCapture = screenshot(); - // Child and BG blended. - mCapture->checkPixel(0, 0, 95, 64, 95); - } -} - -TEST_F(ChildLayerTest, ReparentChildren) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - asTransaction([&](Transaction& t) { - t.reparentChildren(mFGSurfaceControl, mBGSurfaceControl->getHandle()); - }); - - { - mCapture = screenshot(); - mCapture->expectFGColor(64, 64); - // In reparenting we should have exposed the entire foreground surface. - mCapture->expectFGColor(74, 74); - // And the child layer should now begin at 10, 10 (since the BG - // layer is at (0, 0)). - mCapture->expectBGColor(9, 9); - mCapture->expectChildColor(10, 10); - } -} - -TEST_F(ChildLayerTest, ChildrenSurviveParentDestruction) { - sp<SurfaceControl> mGrandChild = - createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); - TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111); - - { - SCOPED_TRACE("Grandchild visible"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 111, 111, 111); - } - - mChild.clear(); - - { - SCOPED_TRACE("After destroying child"); - ScreenCapture::captureScreen(&mCapture); - mCapture->expectFGColor(64, 64); - } - - asTransaction([&](Transaction& t) { - t.reparent(mGrandChild, mFGSurfaceControl->getHandle()); - }); - - { - SCOPED_TRACE("After reparenting grandchild"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 111, 111, 111); - } -} - -TEST_F(ChildLayerTest, ChildrenRelativeZSurvivesParentDestruction) { - sp<SurfaceControl> mGrandChild = - createSurface(mClient, "Grand Child", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); - TransactionUtils::fillSurfaceRGBA8(mGrandChild, 111, 111, 111); - - // draw grand child behind the foreground surface - asTransaction([&](Transaction& t) { - t.setRelativeLayer(mGrandChild, mFGSurfaceControl->getHandle(), -1); - }); - - { - SCOPED_TRACE("Child visible"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 200, 200, 200); - } - - asTransaction([&](Transaction& t) { - t.reparent(mChild, nullptr); - t.reparentChildren(mChild, mFGSurfaceControl->getHandle()); - }); - - { - SCOPED_TRACE("foreground visible reparenting grandchild"); - ScreenCapture::captureScreen(&mCapture); - mCapture->checkPixel(64, 64, 195, 63, 63); - } -} - -TEST_F(ChildLayerTest, DetachChildrenSameClient) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - - asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); }); - - asTransaction([&](Transaction& t) { t.hide(mChild); }); - - // Since the child has the same client as the parent, it will not get - // detached and will be hidden. - { - mCapture = screenshot(); - mCapture->expectFGColor(64, 64); - mCapture->expectFGColor(74, 74); - mCapture->expectFGColor(84, 84); - } -} - -TEST_F(ChildLayerTest, DetachChildrenDifferentClient) { - sp<SurfaceComposerClient> mNewComposerClient = new SurfaceComposerClient; - sp<SurfaceControl> mChildNewClient = - createSurface(mNewComposerClient, "New Child Test Surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - - ASSERT_TRUE(mChildNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(mChildNewClient, 200, 200, 200); - - asTransaction([&](Transaction& t) { - t.hide(mChild); - t.show(mChildNewClient); - t.setPosition(mChildNewClient, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - asTransaction([&](Transaction& t) { t.detachChildren(mFGSurfaceControl); }); - - asTransaction([&](Transaction& t) { t.hide(mChildNewClient); }); - - // Nothing should have changed. - { - mCapture = screenshot(); - mCapture->expectFGColor(64, 64); - mCapture->expectChildColor(74, 74); - mCapture->expectFGColor(84, 84); - } -} - -TEST_F(ChildLayerTest, DetachChildrenThenAttach) { - sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; - sp<SurfaceControl> childNewClient = - newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - - ASSERT_TRUE(childNewClient != nullptr); - ASSERT_TRUE(childNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200); - - Transaction() - .hide(mChild) - .show(childNewClient) - .setPosition(childNewClient, 10, 10) - .setPosition(mFGSurfaceControl, 64, 64) - .apply(); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - Transaction().detachChildren(mFGSurfaceControl).apply(); - Transaction().hide(childNewClient).apply(); - - // Nothing should have changed. - { - mCapture = screenshot(); - mCapture->expectFGColor(64, 64); - mCapture->expectChildColor(74, 74); - mCapture->expectFGColor(84, 84); - } - - sp<SurfaceControl> newParentSurface = createLayer(String8("New Parent Surface"), 32, 32, 0); - fillLayerColor(ISurfaceComposerClient::eFXSurfaceBufferQueue, newParentSurface, Color::RED, 32, - 32); - Transaction() - .setLayer(newParentSurface, INT32_MAX - 1) - .show(newParentSurface) - .setPosition(newParentSurface, 20, 20) - .reparent(childNewClient, newParentSurface->getHandle()) - .apply(); - { - mCapture = screenshot(); - // Child is now hidden. - mCapture->expectColor(Rect(20, 20, 52, 52), Color::RED); - } -} -TEST_F(ChildLayerTest, DetachChildrenWithDeferredTransaction) { - sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; - sp<SurfaceControl> childNewClient = - newComposerClient->createSurface(String8("New Child Test Surface"), 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - - ASSERT_TRUE(childNewClient != nullptr); - ASSERT_TRUE(childNewClient->isValid()); - - TransactionUtils::fillSurfaceRGBA8(childNewClient, 200, 200, 200); - - Transaction() - .hide(mChild) - .show(childNewClient) - .setPosition(childNewClient, 10, 10) - .setPosition(mFGSurfaceControl, 64, 64) - .apply(); - - { - mCapture = screenshot(); - Rect rect = Rect(74, 74, 84, 84); - mCapture->expectBorder(rect, Color{195, 63, 63, 255}); - mCapture->expectColor(rect, Color{200, 200, 200, 255}); - } - - Transaction() - .deferTransactionUntil_legacy(childNewClient, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()) - .apply(); - Transaction().detachChildren(mFGSurfaceControl).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mFGSurfaceControl, Color::RED, 32, 32)); - - // BufferLayer can still dequeue buffers even though there's a detached layer with a - // deferred transaction. - { - SCOPED_TRACE("new buffer"); - mCapture = screenshot(); - Rect rect = Rect(74, 74, 84, 84); - mCapture->expectBorder(rect, Color::RED); - mCapture->expectColor(rect, Color{200, 200, 200, 255}); - } -} - -TEST_F(ChildLayerTest, ChildrenInheritNonTransformScalingFromParent) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - }); - - { - mCapture = screenshot(); - // We've positioned the child in the top left. - mCapture->expectChildColor(0, 0); - // But it's only 10x15. - mCapture->expectFGColor(10, 15); - } - - asTransaction([&](Transaction& t) { - t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - // We cause scaling by 2. - t.setSize(mFGSurfaceControl, 128, 128); - }); - - { - mCapture = screenshot(); - // We've positioned the child in the top left. - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(10, 10); - mCapture->expectChildColor(19, 29); - // And now it should be scaled all the way to 20x30 - mCapture->expectFGColor(20, 30); - } -} - -// Regression test for b/37673612 -TEST_F(ChildLayerTest, ChildrenWithParentBufferTransform) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - }); - - { - mCapture = screenshot(); - // We've positioned the child in the top left. - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(9, 14); - // But it's only 10x15. - mCapture->expectFGColor(10, 15); - } - // We set things up as in b/37673612 so that there is a mismatch between the buffer size and - // the WM specified state size. - asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); }); - sp<Surface> s = mFGSurfaceControl->getSurface(); - auto anw = static_cast<ANativeWindow*>(s.get()); - native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); - native_window_set_buffers_dimensions(anw, 64, 128); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); - waitForPostedBuffers(); - - { - // The child should still be in the same place and not have any strange scaling as in - // b/37673612. - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectFGColor(10, 10); - } -} - -// A child with a buffer transform from its parents should be cropped by its parent bounds. -TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferTransform) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - t.setSize(mChild, 100, 100); - }); - TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); - - { - mCapture = screenshot(); - - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(63, 63); - mCapture->expectBGColor(64, 64); - } - - asTransaction([&](Transaction& t) { t.setSize(mFGSurfaceControl, 128, 64); }); - sp<Surface> s = mFGSurfaceControl->getSurface(); - auto anw = static_cast<ANativeWindow*>(s.get()); - // Apply a 90 transform on the buffer. - native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); - native_window_set_buffers_dimensions(anw, 64, 128); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); - waitForPostedBuffers(); - - // The child should be cropped by the new parent bounds. - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(99, 63); - mCapture->expectFGColor(100, 63); - mCapture->expectBGColor(128, 64); - } -} - -// A child with a scale transform from its parents should be cropped by its parent bounds. -TEST_F(ChildLayerTest, ChildCroppedByParentWithBufferScale) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - t.setSize(mChild, 200, 200); - }); - TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); - - { - mCapture = screenshot(); - - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(63, 63); - mCapture->expectBGColor(64, 64); - } - - asTransaction([&](Transaction& t) { - t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - // Set a scaling by 2. - t.setSize(mFGSurfaceControl, 128, 128); - }); - - // Child should inherit its parents scale but should be cropped by its parent bounds. - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(127, 127); - mCapture->expectBGColor(128, 128); - } -} - -// Regression test for b/127368943 -// Child should ignore the buffer transform but apply parent scale transform. -TEST_F(ChildLayerTest, ChildrenWithParentBufferTransformAndScale) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 0, 0); - t.setPosition(mFGSurfaceControl, 0, 0); - }); - - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(9, 14); - mCapture->expectFGColor(10, 15); - } - - // Change the size of the foreground to 128 * 64 so we can test rotation as well. - asTransaction([&](Transaction& t) { - t.setOverrideScalingMode(mFGSurfaceControl, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); - t.setSize(mFGSurfaceControl, 128, 64); - }); - sp<Surface> s = mFGSurfaceControl->getSurface(); - auto anw = static_cast<ANativeWindow*>(s.get()); - // Apply a 90 transform on the buffer and submit a buffer half the expected size so that we - // have an effective scale of 2.0 applied to the buffer along with a rotation transform. - native_window_set_buffers_transform(anw, NATIVE_WINDOW_TRANSFORM_ROT_90); - native_window_set_buffers_dimensions(anw, 32, 64); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 195, 63, 63); - waitForPostedBuffers(); - - // The child should ignore the buffer transform but apply the 2.0 scale from parent. - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(19, 29); - mCapture->expectFGColor(20, 30); - } -} - -TEST_F(ChildLayerTest, Bug36858924) { - // Destroy the child layer - mChild.clear(); - - // Now recreate it as hidden - mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eHidden, mFGSurfaceControl.get()); - - // Show the child layer in a deferred transaction - asTransaction([&](Transaction& t) { - t.deferTransactionUntil_legacy(mChild, mFGSurfaceControl->getHandle(), - mFGSurfaceControl->getSurface()->getNextFrameNumber()); - t.show(mChild); - }); - - // Render the foreground surface a few times - // - // Prior to the bugfix for b/36858924, this would usually hang while trying to fill the third - // frame because SurfaceFlinger would never process the deferred transaction and would therefore - // never acquire/release the first buffer - ALOGI("Filling 1"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); - ALOGI("Filling 2"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 0, 255); - ALOGI("Filling 3"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 255, 0, 0); - ALOGI("Filling 4"); - TransactionUtils::fillSurfaceRGBA8(mFGSurfaceControl, 0, 255, 0); -} - -TEST_F(ChildLayerTest, Reparent) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - - asTransaction([&](Transaction& t) { t.reparent(mChild, mBGSurfaceControl->getHandle()); }); - - { - mCapture = screenshot(); - mCapture->expectFGColor(64, 64); - // In reparenting we should have exposed the entire foreground surface. - mCapture->expectFGColor(74, 74); - // And the child layer should now begin at 10, 10 (since the BG - // layer is at (0, 0)). - mCapture->expectBGColor(9, 9); - mCapture->expectChildColor(10, 10); - } -} - -TEST_F(ChildLayerTest, ReparentToNoParent) { - asTransaction([&](Transaction& t) { - t.show(mChild); - t.setPosition(mChild, 10, 10); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // But 10 pixels in we should see the child surface - mCapture->expectChildColor(74, 74); - // And 10 more pixels we should be back to the foreground surface - mCapture->expectFGColor(84, 84); - } - asTransaction([&](Transaction& t) { t.reparent(mChild, nullptr); }); - { - mCapture = screenshot(); - // The surface should now be offscreen. - mCapture->expectFGColor(64, 64); - mCapture->expectFGColor(74, 74); - mCapture->expectFGColor(84, 84); - } -} - -TEST_F(ChildLayerTest, ReparentFromNoParent) { - sp<SurfaceControl> newSurface = createLayer(String8("New Surface"), 10, 10, 0); - ASSERT_TRUE(newSurface != nullptr); - ASSERT_TRUE(newSurface->isValid()); - - TransactionUtils::fillSurfaceRGBA8(newSurface, 63, 195, 63); - asTransaction([&](Transaction& t) { - t.hide(mChild); - t.show(newSurface); - t.setPosition(newSurface, 10, 10); - t.setLayer(newSurface, INT32_MAX - 2); - t.setPosition(mFGSurfaceControl, 64, 64); - }); - - { - mCapture = screenshot(); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // At 10, 10 we should see the new surface - mCapture->checkPixel(10, 10, 63, 195, 63); - } - - asTransaction([&](Transaction& t) { t.reparent(newSurface, mFGSurfaceControl->getHandle()); }); - - { - mCapture = screenshot(); - // newSurface will now be a child of mFGSurface so it will be 10, 10 offset from - // mFGSurface, putting it at 74, 74. - mCapture->expectFGColor(64, 64); - mCapture->checkPixel(74, 74, 63, 195, 63); - mCapture->expectFGColor(84, 84); - } -} - -TEST_F(ChildLayerTest, NestedChildren) { - sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mChild.get()); - TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50); - - { - mCapture = screenshot(); - // Expect the grandchild to begin at 64, 64 because it's a child of mChild layer - // which begins at 64, 64 - mCapture->checkPixel(64, 64, 50, 50, 50); - } -} - -TEST_F(ChildLayerTest, ChildLayerRelativeLayer) { - sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 128, 128, 0); - TransactionUtils::fillSurfaceRGBA8(relative, 255, 255, 255); - - Transaction t; - t.setLayer(relative, INT32_MAX) - .setRelativeLayer(mChild, relative->getHandle(), 1) - .setPosition(mFGSurfaceControl, 0, 0) - .apply(true); - - // We expect that the child should have been elevated above our - // INT_MAX layer even though it's not a child of it. - { - mCapture = screenshot(); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(9, 9); - mCapture->checkPixel(10, 10, 255, 255, 255); - } -} - -class BoundlessLayerTest : public LayerUpdateTest { -protected: - std::unique_ptr<ScreenCapture> mCapture; -}; - -// Verify setting a size on a buffer layer has no effect. -TEST_F(BoundlessLayerTest, BufferLayerIgnoresSize) { - sp<SurfaceControl> bufferLayer = - createSurface(mClient, "BufferLayer", 45, 45, PIXEL_FORMAT_RGBA_8888, 0, - mFGSurfaceControl.get()); - ASSERT_TRUE(bufferLayer->isValid()); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(bufferLayer, Color::BLACK, 30, 30)); - asTransaction([&](Transaction& t) { t.show(bufferLayer); }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Foreground Surface bounds must be color layer - mCapture->expectColor(Rect(64, 64, 94, 94), Color::BLACK); - // Buffer layer should not extend past buffer bounds - mCapture->expectFGColor(95, 95); - } -} - -// Verify a boundless color layer will fill its parent bounds. The parent has a buffer size -// which will crop the color layer. -TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentBufferBounds) { - sp<SurfaceControl> colorLayer = - createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get()); - ASSERT_TRUE(colorLayer->isValid()); - asTransaction([&](Transaction& t) { - t.setColor(colorLayer, half3{0, 0, 0}); - t.show(colorLayer); - }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Foreground Surface bounds must be color layer - mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); - // Color layer should not extend past foreground bounds - mCapture->expectBGColor(129, 129); - } -} - -// Verify a boundless color layer will fill its parent bounds. The parent has no buffer but has -// a crop which will be used to crop the color layer. -TEST_F(BoundlessLayerTest, BoundlessColorLayerFillsParentCropBounds) { - sp<SurfaceControl> cropLayer = createSurface(mClient, "CropLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, mFGSurfaceControl.get()); - ASSERT_TRUE(cropLayer->isValid()); - sp<SurfaceControl> colorLayer = - createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, cropLayer.get()); - ASSERT_TRUE(colorLayer->isValid()); - asTransaction([&](Transaction& t) { - t.setCrop_legacy(cropLayer, Rect(5, 5, 10, 10)); - t.setColor(colorLayer, half3{0, 0, 0}); - t.show(cropLayer); - t.show(colorLayer); - }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // 5 pixels from the foreground we should see the child surface - mCapture->expectColor(Rect(69, 69, 74, 74), Color::BLACK); - // 10 pixels from the foreground we should be back to the foreground surface - mCapture->expectFGColor(74, 74); - } -} - -// Verify for boundless layer with no children, their transforms have no effect. -TEST_F(BoundlessLayerTest, BoundlessColorLayerTransformHasNoEffect) { - sp<SurfaceControl> colorLayer = - createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, mFGSurfaceControl.get()); - ASSERT_TRUE(colorLayer->isValid()); - asTransaction([&](Transaction& t) { - t.setPosition(colorLayer, 320, 320); - t.setMatrix(colorLayer, 2, 0, 0, 2); - t.setColor(colorLayer, half3{0, 0, 0}); - t.show(colorLayer); - }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Foreground Surface bounds must be color layer - mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); - // Color layer should not extend past foreground bounds - mCapture->expectBGColor(129, 129); - } -} - -// Verify for boundless layer with children, their transforms have an effect. -TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerCanSetTransform) { - sp<SurfaceControl> boundlessLayerRightShift = - createSurface(mClient, "BoundlessLayerRightShift", 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, mFGSurfaceControl.get()); - ASSERT_TRUE(boundlessLayerRightShift->isValid()); - sp<SurfaceControl> boundlessLayerDownShift = - createSurface(mClient, "BoundlessLayerLeftShift", 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, boundlessLayerRightShift.get()); - ASSERT_TRUE(boundlessLayerDownShift->isValid()); - sp<SurfaceControl> colorLayer = - createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, boundlessLayerDownShift.get()); - ASSERT_TRUE(colorLayer->isValid()); - asTransaction([&](Transaction& t) { - t.setPosition(boundlessLayerRightShift, 32, 0); - t.show(boundlessLayerRightShift); - t.setPosition(boundlessLayerDownShift, 0, 32); - t.show(boundlessLayerDownShift); - t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); - t.setColor(colorLayer, half3{0, 0, 0}); - t.show(colorLayer); - }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Top left of foreground must now be visible - mCapture->expectFGColor(64, 64); - // Foreground Surface bounds must be color layer - mCapture->expectColor(Rect(96, 96, 128, 128), Color::BLACK); - // Color layer should not extend past foreground bounds - mCapture->expectBGColor(129, 129); - } -} - -// Verify child layers do not get clipped if they temporarily move into the negative -// coordinate space as the result of an intermediate transformation. -TEST_F(BoundlessLayerTest, IntermediateBoundlessLayerDoNotCrop) { - sp<SurfaceControl> boundlessLayer = - mClient->createSurface(String8("BoundlessLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - 0 /* flags */, mFGSurfaceControl.get()); - ASSERT_TRUE(boundlessLayer != nullptr); - ASSERT_TRUE(boundlessLayer->isValid()); - sp<SurfaceControl> colorLayer = - mClient->createSurface(String8("ColorLayer"), 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, boundlessLayer.get()); - ASSERT_TRUE(colorLayer != nullptr); - ASSERT_TRUE(colorLayer->isValid()); - asTransaction([&](Transaction& t) { - // shift child layer off bounds. If this layer was not boundless, we will - // expect the child layer to be cropped. - t.setPosition(boundlessLayer, 32, 32); - t.show(boundlessLayer); - t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); - // undo shift by parent - t.setPosition(colorLayer, -32, -32); - t.setColor(colorLayer, half3{0, 0, 0}); - t.show(colorLayer); - }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Foreground Surface bounds must be color layer - mCapture->expectColor(Rect(64, 64, 128, 128), Color::BLACK); - // Color layer should not extend past foreground bounds - mCapture->expectBGColor(129, 129); - } -} - -// Verify for boundless root layers with children, their transforms have an effect. -TEST_F(BoundlessLayerTest, RootBoundlessLayerCanSetTransform) { - sp<SurfaceControl> rootBoundlessLayer = createSurface(mClient, "RootBoundlessLayer", 0, 0, - PIXEL_FORMAT_RGBA_8888, 0 /* flags */); - ASSERT_TRUE(rootBoundlessLayer->isValid()); - sp<SurfaceControl> colorLayer = - createSurface(mClient, "ColorLayer", 0, 0, PIXEL_FORMAT_RGBA_8888, - ISurfaceComposerClient::eFXSurfaceColor, rootBoundlessLayer.get()); - - ASSERT_TRUE(colorLayer->isValid()); - asTransaction([&](Transaction& t) { - t.setLayer(rootBoundlessLayer, INT32_MAX - 1); - t.setPosition(rootBoundlessLayer, 32, 32); - t.show(rootBoundlessLayer); - t.setCrop_legacy(colorLayer, Rect(0, 0, 64, 64)); - t.setColor(colorLayer, half3{0, 0, 0}); - t.show(colorLayer); - t.hide(mFGSurfaceControl); - }); - { - mCapture = screenshot(); - // Top left of background must now be visible - mCapture->expectBGColor(0, 0); - // Top left of foreground must now be visible - mCapture->expectBGColor(31, 31); - // Foreground Surface bounds must be color layer - mCapture->expectColor(Rect(32, 32, 96, 96), Color::BLACK); - // Color layer should not extend past foreground bounds - mCapture->expectBGColor(97, 97); - } -} - -class ScreenCaptureTest : public LayerUpdateTest { -protected: - std::unique_ptr<ScreenCapture> mCapture; -}; - -TEST_F(ScreenCaptureTest, CaptureSingleLayer) { - auto bgHandle = mBGSurfaceControl->getHandle(); - ScreenCapture::captureLayers(&mCapture, bgHandle); - mCapture->expectBGColor(0, 0); - // Doesn't capture FG layer which is at 64, 64 - mCapture->expectBGColor(64, 64); -} - -TEST_F(ScreenCaptureTest, CaptureLayerWithChild) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - - SurfaceComposerClient::Transaction().show(child).apply(true); - - // Captures mFGSurfaceControl layer and its child. - ScreenCapture::captureLayers(&mCapture, fgHandle); - mCapture->expectFGColor(10, 10); - mCapture->expectChildColor(0, 0); -} - -TEST_F(ScreenCaptureTest, CaptureLayerChildOnly) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - - SurfaceComposerClient::Transaction().show(child).apply(true); - - // Captures mFGSurfaceControl's child - ScreenCapture::captureChildLayers(&mCapture, fgHandle); - mCapture->checkPixel(10, 10, 0, 0, 0); - mCapture->expectChildColor(0, 0); -} - -TEST_F(ScreenCaptureTest, CaptureLayerExclude) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200); - - SurfaceComposerClient::Transaction() - .show(child) - .show(child2) - .setLayer(child, 1) - .setLayer(child2, 2) - .apply(true); - - // Child2 would be visible but its excluded, so we should see child1 color instead. - ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()}); - mCapture->checkPixel(10, 10, 0, 0, 0); - mCapture->checkPixel(0, 0, 200, 200, 200); -} - -// Like the last test but verifies that children are also exclude. -TEST_F(ScreenCaptureTest, CaptureLayerExcludeTree) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - sp<SurfaceControl> child2 = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200); - sp<SurfaceControl> child3 = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, child2.get()); - TransactionUtils::fillSurfaceRGBA8(child2, 200, 0, 200); - - SurfaceComposerClient::Transaction() - .show(child) - .show(child2) - .show(child3) - .setLayer(child, 1) - .setLayer(child2, 2) - .apply(true); - - // Child2 would be visible but its excluded, so we should see child1 color instead. - ScreenCapture::captureChildLayersExcluding(&mCapture, fgHandle, {child2->getHandle()}); - mCapture->checkPixel(10, 10, 0, 0, 0); - mCapture->checkPixel(0, 0, 200, 200, 200); -} - -TEST_F(ScreenCaptureTest, CaptureTransparent) { - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - - SurfaceComposerClient::Transaction().show(child).apply(true); - - auto childHandle = child->getHandle(); - - // Captures child - ScreenCapture::captureLayers(&mCapture, childHandle, {0, 0, 10, 20}); - mCapture->expectColor(Rect(0, 0, 9, 9), {200, 200, 200, 255}); - // Area outside of child's bounds is transparent. - mCapture->expectColor(Rect(0, 10, 9, 19), {0, 0, 0, 0}); -} - -TEST_F(ScreenCaptureTest, DontCaptureRelativeOutsideTree) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - ASSERT_NE(nullptr, child.get()) << "failed to create surface"; - sp<SurfaceControl> relative = createLayer(String8("Relative surface"), 10, 10, 0); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100); - - SurfaceComposerClient::Transaction() - .show(child) - // Set relative layer above fg layer so should be shown above when computing all layers. - .setRelativeLayer(relative, fgHandle, 1) - .show(relative) - .apply(true); - - // Captures mFGSurfaceControl layer and its child. Relative layer shouldn't be captured. - ScreenCapture::captureLayers(&mCapture, fgHandle); - mCapture->expectFGColor(10, 10); - mCapture->expectChildColor(0, 0); -} - -TEST_F(ScreenCaptureTest, CaptureRelativeInTree) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - sp<SurfaceControl> relative = createSurface(mClient, "Relative surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - TransactionUtils::fillSurfaceRGBA8(relative, 100, 100, 100); - - SurfaceComposerClient::Transaction() - .show(child) - // Set relative layer below fg layer but relative to child layer so it should be shown - // above child layer. - .setLayer(relative, -1) - .setRelativeLayer(relative, child->getHandle(), 1) - .show(relative) - .apply(true); - - // Captures mFGSurfaceControl layer and its children. Relative layer is a child of fg so its - // relative value should be taken into account, placing it above child layer. - ScreenCapture::captureLayers(&mCapture, fgHandle); - mCapture->expectFGColor(10, 10); - // Relative layer is showing on top of child layer - mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255}); -} - -// In the following tests we verify successful skipping of a parent layer, -// so we use the same verification logic and only change how we mutate -// the parent layer to verify that various properties are ignored. -class ScreenCaptureChildOnlyTest : public LayerUpdateTest { -public: - void SetUp() override { - LayerUpdateTest::SetUp(); - - mChild = createSurface(mClient, "Child surface", 10, 10, PIXEL_FORMAT_RGBA_8888, 0, - mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(mChild, 200, 200, 200); - - SurfaceComposerClient::Transaction().show(mChild).apply(true); - } - - void verify(std::function<void()> verifyStartingState) { - // Verify starting state before a screenshot is taken. - verifyStartingState(); - - // Verify child layer does not inherit any of the properties of its - // parent when its screenshot is captured. - auto fgHandle = mFGSurfaceControl->getHandle(); - ScreenCapture::captureChildLayers(&mCapture, fgHandle); - mCapture->checkPixel(10, 10, 0, 0, 0); - mCapture->expectChildColor(0, 0); - - // Verify all assumptions are still true after the screenshot is taken. - verifyStartingState(); - } - - std::unique_ptr<ScreenCapture> mCapture; - sp<SurfaceControl> mChild; -}; - -// Regression test b/76099859 -TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentVisibility) { - - SurfaceComposerClient::Transaction().hide(mFGSurfaceControl).apply(true); - - // Even though the parent is hidden we should still capture the child. - - // Before and after reparenting, verify child is properly hidden - // when rendering full-screen. - verify([&] { screenshot()->expectBGColor(64, 64); }); -} - -TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresParentCrop) { - SurfaceComposerClient::Transaction() - .setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 1, 1)) - .apply(true); - - // Even though the parent is cropped out we should still capture the child. - - // Before and after reparenting, verify child is cropped by parent. - verify([&] { screenshot()->expectBGColor(65, 65); }); -} - -// Regression test b/124372894 -TEST_F(ScreenCaptureChildOnlyTest, CaptureLayerIgnoresTransform) { - SurfaceComposerClient::Transaction().setMatrix(mFGSurfaceControl, 2, 0, 0, 2).apply(true); - - // We should not inherit the parent scaling. - - // Before and after reparenting, verify child is properly scaled. - verify([&] { screenshot()->expectChildColor(80, 80); }); -} - - -TEST_F(ScreenCaptureTest, CaptureLayerWithGrandchild) { - auto fgHandle = mFGSurfaceControl->getHandle(); - - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - - sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5, - PIXEL_FORMAT_RGBA_8888, 0, child.get()); - - TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50); - SurfaceComposerClient::Transaction() - .show(child) - .setPosition(grandchild, 5, 5) - .show(grandchild) - .apply(true); - - // Captures mFGSurfaceControl, its child, and the grandchild. - ScreenCapture::captureLayers(&mCapture, fgHandle); - mCapture->expectFGColor(10, 10); - mCapture->expectChildColor(0, 0); - mCapture->checkPixel(5, 5, 50, 50, 50); -} - -TEST_F(ScreenCaptureTest, CaptureChildOnly) { - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - auto childHandle = child->getHandle(); - - SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true); - - // Captures only the child layer, and not the parent. - ScreenCapture::captureLayers(&mCapture, childHandle); - mCapture->expectChildColor(0, 0); - mCapture->expectChildColor(9, 9); -} - -TEST_F(ScreenCaptureTest, CaptureGrandchildOnly) { - sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10, - PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get()); - TransactionUtils::fillSurfaceRGBA8(child, 200, 200, 200); - auto childHandle = child->getHandle(); - - sp<SurfaceControl> grandchild = createSurface(mClient, "Grandchild surface", 5, 5, - PIXEL_FORMAT_RGBA_8888, 0, child.get()); - TransactionUtils::fillSurfaceRGBA8(grandchild, 50, 50, 50); - - SurfaceComposerClient::Transaction() - .show(child) - .setPosition(grandchild, 5, 5) - .show(grandchild) - .apply(true); - - auto grandchildHandle = grandchild->getHandle(); - - // Captures only the grandchild. - ScreenCapture::captureLayers(&mCapture, grandchildHandle); - mCapture->checkPixel(0, 0, 50, 50, 50); - mCapture->checkPixel(4, 4, 50, 50, 50); -} - -TEST_F(ScreenCaptureTest, CaptureCrop) { - sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); - sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30, - PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); - - SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX - 1) - .show(redLayer) - .show(blueLayer) - .apply(true); - - auto redLayerHandle = redLayer->getHandle(); - - // Capturing full screen should have both red and blue are visible. - ScreenCapture::captureLayers(&mCapture, redLayerHandle); - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); - - const Rect crop = Rect(0, 0, 30, 30); - ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop); - // Capturing the cropped screen, cropping out the shown red area, should leave only the blue - // area visible. - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - mCapture->checkPixel(30, 30, 0, 0, 0); -} - -TEST_F(ScreenCaptureTest, CaptureSize) { - sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); - sp<SurfaceControl> blueLayer = createSurface(mClient, "Blue surface", 30, 30, - PIXEL_FORMAT_RGBA_8888, 0, redLayer.get()); - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(blueLayer, Color::BLUE, 30, 30)); - - SurfaceComposerClient::Transaction() - .setLayer(redLayer, INT32_MAX - 1) - .show(redLayer) - .show(blueLayer) - .apply(true); - - auto redLayerHandle = redLayer->getHandle(); - - // Capturing full screen should have both red and blue are visible. - ScreenCapture::captureLayers(&mCapture, redLayerHandle); - mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED); - - ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5); - // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area. - mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE); - // red area below the blue area - mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED); - // red area to the right of the blue area - mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED); - mCapture->checkPixel(30, 30, 0, 0, 0); -} - -TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { - sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60, 0); - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60)); - - auto redLayerHandle = redLayer->getHandle(); - redLayer.clear(); - SurfaceComposerClient::Transaction().apply(true); - - sp<GraphicBuffer> outBuffer; - - // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND - sp<ISurfaceComposer> sf(ComposerService::getComposerService()); - ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); -} - - -class DereferenceSurfaceControlTest : public LayerTransactionTest { -protected: - void SetUp() override { - LayerTransactionTest::SetUp(); - bgLayer = createLayer("BG layer", 20, 20); - fillBufferQueueLayerColor(bgLayer, Color::RED, 20, 20); - fgLayer = createLayer("FG layer", 20, 20); - fillBufferQueueLayerColor(fgLayer, Color::BLUE, 20, 20); - Transaction().setLayer(fgLayer, mLayerZBase + 1).apply(); - { - SCOPED_TRACE("before anything"); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE); - } - } - void TearDown() override { - LayerTransactionTest::TearDown(); - bgLayer = 0; - fgLayer = 0; - } - - sp<SurfaceControl> bgLayer; - sp<SurfaceControl> fgLayer; -}; - -TEST_F(DereferenceSurfaceControlTest, LayerNotInTransaction) { - fgLayer = nullptr; - { - SCOPED_TRACE("after setting null"); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 20, 20), Color::RED); - } -} - -TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) { - auto transaction = Transaction().show(fgLayer); - fgLayer = nullptr; - { - SCOPED_TRACE("after setting null"); - auto shot = screenshot(); - shot->expectColor(Rect(0, 0, 20, 20), Color::BLUE); - } -} - -class MultiDisplayLayerBoundsTest : public LayerTransactionTest { -protected: - virtual void SetUp() { - LayerTransactionTest::SetUp(); - ASSERT_EQ(NO_ERROR, mClient->initCheck()); - - mMainDisplay = SurfaceComposerClient::getInternalDisplayToken(); - SurfaceComposerClient::getDisplayInfo(mMainDisplay, &mMainDisplayInfo); - - sp<IGraphicBufferConsumer> consumer; - BufferQueue::createBufferQueue(&mProducer, &consumer); - consumer->setConsumerName(String8("Virtual disp consumer")); - consumer->setDefaultBufferSize(mMainDisplayInfo.w, mMainDisplayInfo.h); - } - - virtual void TearDown() { - SurfaceComposerClient::destroyDisplay(mVirtualDisplay); - LayerTransactionTest::TearDown(); - mColorLayer = 0; - } - - void createDisplay(const Rect& layerStackRect, uint32_t layerStack) { - mVirtualDisplay = - SurfaceComposerClient::createDisplay(String8("VirtualDisplay"), false /*secure*/); - asTransaction([&](Transaction& t) { - t.setDisplaySurface(mVirtualDisplay, mProducer); - t.setDisplayLayerStack(mVirtualDisplay, layerStack); - t.setDisplayProjection(mVirtualDisplay, mMainDisplayInfo.orientation, layerStackRect, - Rect(mMainDisplayInfo.w, mMainDisplayInfo.h)); - }); - } - - void createColorLayer(uint32_t layerStack) { - mColorLayer = - createSurface(mClient, "ColorLayer", 0 /* buffer width */, 0 /* buffer height */, - PIXEL_FORMAT_RGBA_8888, ISurfaceComposerClient::eFXSurfaceColor); - ASSERT_TRUE(mColorLayer != nullptr); - ASSERT_TRUE(mColorLayer->isValid()); - asTransaction([&](Transaction& t) { - t.setLayerStack(mColorLayer, layerStack); - t.setCrop_legacy(mColorLayer, Rect(0, 0, 30, 40)); - t.setLayer(mColorLayer, INT32_MAX - 2); - t.setColor(mColorLayer, - half3{mExpectedColor.r / 255.0f, mExpectedColor.g / 255.0f, - mExpectedColor.b / 255.0f}); - t.show(mColorLayer); - }); - } - - DisplayInfo mMainDisplayInfo; - sp<IBinder> mMainDisplay; - sp<IBinder> mVirtualDisplay; - sp<IGraphicBufferProducer> mProducer; - sp<SurfaceControl> mColorLayer; - Color mExpectedColor = {63, 63, 195, 255}; -}; - -TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInVirtualDisplay) { - createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 1 /* layerStack */); - createColorLayer(1 /* layerStack */); - - asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); }); - - // Verify color layer does not render on main display. - std::unique_ptr<ScreenCapture> sc; - ScreenCapture::captureScreen(&sc, mMainDisplay); - sc->expectColor(Rect(10, 10, 40, 50), {0, 0, 0, 255}); - sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); - - // Verify color layer renders correctly on virtual display. - ScreenCapture::captureScreen(&sc, mVirtualDisplay); - sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor); - sc->expectColor(Rect(1, 1, 9, 9), {0, 0, 0, 0}); -} - -TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) { - // Create a display and set its layer stack to the main display's layer stack so - // the contents of the main display are mirrored on to the virtual display. - - // Assumption here is that the new mirrored display has the same viewport as the - // primary display that it is mirroring. - createDisplay({mMainDisplayInfo.viewportW, mMainDisplayInfo.viewportH}, 0 /* layerStack */); - createColorLayer(0 /* layerStack */); - - asTransaction([&](Transaction& t) { t.setPosition(mColorLayer, 10, 10); }); - - // Verify color layer renders correctly on main display and it is mirrored on the - // virtual display. - std::unique_ptr<ScreenCapture> sc; - ScreenCapture::captureScreen(&sc, mMainDisplay); - sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor); - sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); - - ScreenCapture::captureScreen(&sc, mVirtualDisplay); - sc->expectColor(Rect(10, 10, 40, 50), mExpectedColor); - sc->expectColor(Rect(0, 0, 9, 9), {0, 0, 0, 255}); -} - -class DisplayActiveConfigTest : public ::testing::Test { -protected: - void SetUp() override { - mDisplayToken = SurfaceComposerClient::getInternalDisplayToken(); - SurfaceComposerClient::getDisplayConfigs(mDisplayToken, &mDisplayconfigs); - EXPECT_GT(mDisplayconfigs.size(), 0); - - // set display power to on to make sure config can be changed - SurfaceComposerClient::setDisplayPowerMode(mDisplayToken, HWC_POWER_MODE_NORMAL); - } - - sp<IBinder> mDisplayToken; - Vector<DisplayInfo> mDisplayconfigs; -}; - -TEST_F(DisplayActiveConfigTest, allConfigsAllowed) { - std::vector<int32_t> allowedConfigs; - - // Add all configs to the allowed configs - for (int i = 0; i < mDisplayconfigs.size(); i++) { - allowedConfigs.push_back(i); - } - - status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); - EXPECT_EQ(res, NO_ERROR); - - std::vector<int32_t> outConfigs; - res = SurfaceComposerClient::getAllowedDisplayConfigs(mDisplayToken, &outConfigs); - EXPECT_EQ(res, NO_ERROR); - EXPECT_EQ(allowedConfigs, outConfigs); -} - -TEST_F(DisplayActiveConfigTest, changeAllowedConfig) { - // we need at least 2 configs available for this test - if (mDisplayconfigs.size() <= 1) return; - - int activeConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); - - // We want to set the allowed config to everything but the active config - std::vector<int32_t> allowedConfigs; - for (int i = 0; i < mDisplayconfigs.size(); i++) { - if (i != activeConfig) { - allowedConfigs.push_back(i); - } - } - - status_t res = SurfaceComposerClient::setAllowedDisplayConfigs(mDisplayToken, allowedConfigs); - EXPECT_EQ(res, NO_ERROR); - - // Allow some time for the config change - std::this_thread::sleep_for(200ms); - - int newActiveConfig = SurfaceComposerClient::getActiveConfig(mDisplayToken); - EXPECT_NE(activeConfig, newActiveConfig); - - // Make sure the new config is part of allowed config - EXPECT_TRUE(std::find(allowedConfigs.begin(), allowedConfigs.end(), newActiveConfig) != - allowedConfigs.end()); -} - -class RelativeZTest : public LayerTransactionTest { -protected: - virtual void SetUp() { - LayerTransactionTest::SetUp(); - ASSERT_EQ(NO_ERROR, mClient->initCheck()); - - const auto display = SurfaceComposerClient::getInternalDisplayToken(); - ASSERT_FALSE(display == nullptr); - - // Back layer - mBackgroundLayer = createColorLayer("Background layer", Color::RED); - - // Front layer - mForegroundLayer = createColorLayer("Foreground layer", Color::GREEN); - - asTransaction([&](Transaction& t) { - t.setDisplayLayerStack(display, 0); - t.setLayer(mBackgroundLayer, INT32_MAX - 2).show(mBackgroundLayer); - t.setLayer(mForegroundLayer, INT32_MAX - 1).show(mForegroundLayer); - }); - } - - virtual void TearDown() { - LayerTransactionTest::TearDown(); - mBackgroundLayer = 0; - mForegroundLayer = 0; - } - - sp<SurfaceControl> mBackgroundLayer; - sp<SurfaceControl> mForegroundLayer; -}; - -// When a layer is reparented offscreen, remove relative z order if the relative parent -// is still onscreen so that the layer is not drawn. -TEST_F(RelativeZTest, LayerRemoved) { - std::unique_ptr<ScreenCapture> sc; - - // Background layer (RED) - // Child layer (WHITE) (relative to foregroud layer) - // Foregroud layer (GREEN) - sp<SurfaceControl> childLayer = - createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get()); - - Transaction{} - .setRelativeLayer(childLayer, mForegroundLayer->getHandle(), 1) - .show(childLayer) - .apply(); - - { - // The childLayer should be in front of the FG control. - ScreenCapture::captureScreen(&sc); - sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); - } - - // Background layer (RED) - // Foregroud layer (GREEN) - Transaction{}.reparent(childLayer, nullptr).apply(); - - // Background layer (RED) - // Child layer (WHITE) - // Foregroud layer (GREEN) - Transaction{}.reparent(childLayer, mBackgroundLayer->getHandle()).apply(); - - { - // The relative z info for child layer should be reset, leaving FG control on top. - ScreenCapture::captureScreen(&sc); - sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); - } -} - -// When a layer is reparented offscreen, preseve relative z order if the relative parent -// is also offscreen. Regression test b/132613412 -TEST_F(RelativeZTest, LayerRemovedOffscreenRelativeParent) { - std::unique_ptr<ScreenCapture> sc; - - // Background layer (RED) - // Foregroud layer (GREEN) - // child level 1 (WHITE) - // child level 2a (BLUE) - // child level 3 (GREEN) (relative to child level 2b) - // child level 2b (BLACK) - sp<SurfaceControl> childLevel1 = - createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get()); - sp<SurfaceControl> childLevel2a = - createColorLayer("child level 2a", Color::BLUE, childLevel1.get()); - sp<SurfaceControl> childLevel2b = - createColorLayer("child level 2b", Color::BLACK, childLevel1.get()); - sp<SurfaceControl> childLevel3 = - createColorLayer("child level 3", Color::GREEN, childLevel2a.get()); - - Transaction{} - .setRelativeLayer(childLevel3, childLevel2b->getHandle(), 1) - .show(childLevel2a) - .show(childLevel2b) - .show(childLevel3) - .apply(); - - { - // The childLevel3 should be in front of childLevel2b. - ScreenCapture::captureScreen(&sc); - sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); - } - - // Background layer (RED) - // Foregroud layer (GREEN) - Transaction{}.reparent(childLevel1, nullptr).apply(); - - // Background layer (RED) - // Foregroud layer (GREEN) - // child level 1 (WHITE) - // child level 2 back (BLUE) - // child level 3 (GREEN) (relative to child level 2b) - // child level 2 front (BLACK) - Transaction{}.reparent(childLevel1, mForegroundLayer->getHandle()).apply(); - - { - // Nothing should change at this point since relative z info was preserved. - ScreenCapture::captureScreen(&sc); - sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); - } -} - -// This test ensures that when we drop an app buffer in SurfaceFlinger, we merge -// the dropped buffer's damage region into the next buffer's damage region. If -// we don't do this, we'll report an incorrect damage region to hardware -// composer, resulting in broken rendering. This test checks the BufferQueue -// case. -// -// Unfortunately, we don't currently have a way to inspect the damage region -// SurfaceFlinger sends to hardware composer from a test, so this test requires -// the dev to manually watch the device's screen during the test to spot broken -// rendering. Because the results can't be automatically verified, this test is -// marked disabled. -TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDroppingBuffers) { - const int width = mDisplayWidth; - const int height = mDisplayHeight; - sp<SurfaceControl> layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", width, height)); - const auto producer = layer->getIGraphicBufferProducer(); - const sp<IProducerListener> dummyListener(new DummyProducerListener); - IGraphicBufferProducer::QueueBufferOutput queueBufferOutput; - ASSERT_EQ(OK, - producer->connect(dummyListener, NATIVE_WINDOW_API_CPU, true, &queueBufferOutput)); - - std::map<int, sp<GraphicBuffer>> slotMap; - auto slotToBuffer = [&](int slot, sp<GraphicBuffer>* buf) { - ASSERT_NE(nullptr, buf); - const auto iter = slotMap.find(slot); - ASSERT_NE(slotMap.end(), iter); - *buf = iter->second; - }; - - auto dequeue = [&](int* outSlot) { - ASSERT_NE(nullptr, outSlot); - *outSlot = -1; - int slot; - sp<Fence> fence; - uint64_t age; - FrameEventHistoryDelta timestamps; - const status_t dequeueResult = - producer->dequeueBuffer(&slot, &fence, width, height, PIXEL_FORMAT_RGBA_8888, - GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN, - &age, ×tamps); - if (dequeueResult == IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) { - sp<GraphicBuffer> newBuf; - ASSERT_EQ(OK, producer->requestBuffer(slot, &newBuf)); - ASSERT_NE(nullptr, newBuf.get()); - slotMap[slot] = newBuf; - } else { - ASSERT_EQ(OK, dequeueResult); - } - *outSlot = slot; - }; - - auto queue = [&](int slot, const Region& damage, nsecs_t displayTime) { - IGraphicBufferProducer::QueueBufferInput input( - /*timestamp=*/displayTime, /*isAutoTimestamp=*/false, HAL_DATASPACE_UNKNOWN, - /*crop=*/Rect::EMPTY_RECT, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW, - /*transform=*/0, Fence::NO_FENCE); - input.setSurfaceDamage(damage); - IGraphicBufferProducer::QueueBufferOutput output; - ASSERT_EQ(OK, producer->queueBuffer(slot, input, &output)); - }; - - auto fillAndPostBuffers = [&](const Color& color) { - int slot1; - ASSERT_NO_FATAL_FAILURE(dequeue(&slot1)); - int slot2; - ASSERT_NO_FATAL_FAILURE(dequeue(&slot2)); - - sp<GraphicBuffer> buf1; - ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot1, &buf1)); - sp<GraphicBuffer> buf2; - ASSERT_NO_FATAL_FAILURE(slotToBuffer(slot2, &buf2)); - TransactionUtils::fillGraphicBufferColor(buf1, Rect(width, height), color); - TransactionUtils::fillGraphicBufferColor(buf2, Rect(width, height), color); - - const auto displayTime = systemTime() + milliseconds_to_nanoseconds(100); - ASSERT_NO_FATAL_FAILURE(queue(slot1, Region::INVALID_REGION, displayTime)); - ASSERT_NO_FATAL_FAILURE( - queue(slot2, Region(Rect(width / 3, height / 3, 2 * width / 3, 2 * height / 3)), - displayTime)); - }; - - const auto startTime = systemTime(); - const std::array<Color, 3> colors = {Color::RED, Color::GREEN, Color::BLUE}; - int colorIndex = 0; - while (nanoseconds_to_seconds(systemTime() - startTime) < 10) { - ASSERT_NO_FATAL_FAILURE(fillAndPostBuffers(colors[colorIndex++ % colors.size()])); - std::this_thread::sleep_for(1s); - } - - ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU)); -} - -} // namespace android |