/* * 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. */ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #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 mBackgroundLayer; sp 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 sc; // Background layer (RED) // Child layer (WHITE) (relative to foregroud layer) // Foregroud layer (GREEN) sp childLayer = createColorLayer("Child layer", Color::BLUE, mBackgroundLayer.get()); Transaction{}.setRelativeLayer(childLayer, mForegroundLayer, 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).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 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 childLevel1 = createColorLayer("child level 1", Color::WHITE, mForegroundLayer.get()); sp childLevel2a = createColorLayer("child level 2a", Color::BLUE, childLevel1.get()); sp childLevel2b = createColorLayer("child level 2b", Color::BLACK, childLevel1.get()); sp childLevel3 = createColorLayer("child level 3", Color::GREEN, childLevel2a.get()); Transaction{} .setRelativeLayer(childLevel3, childLevel2b, 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).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); } } TEST_F(RelativeZTest, LayerAndRelativeRemoved) { std::unique_ptr sc; // Background layer (RED) // Foregroud layer (GREEN) // Child layer (BLUE) (relative to relativeToLayer layer) // Relative layer (WHITE) sp childLayer = createColorLayer("Child layer", Color::BLUE, mForegroundLayer.get()); sp relativeToLayer = createColorLayer("Relative layer", Color::WHITE, mForegroundLayer.get()); Transaction{} .setRelativeLayer(childLayer, relativeToLayer, 1) .show(childLayer) .show(relativeToLayer) .apply(); { // The childLayer should be in front of relativeToLayer. ScreenCapture::captureScreen(&sc); sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); } // Remove layer that childLayer is relative to // Background layer (RED) // Foregroud layer (GREEN) // Child layer (BLUE) (relative to relativeToLayer layer) Transaction{}.reparent(relativeToLayer, nullptr).apply(); relativeToLayer = 0; { // The child layer is relative to an deleted layer so it won't be drawn. ScreenCapture::captureScreen(&sc); sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); } // Background layer (RED) // Foregroud layer (GREEN) Transaction{}.reparent(childLayer, nullptr).apply(); { // The child layer is offscreen, so it won't be drawn. ScreenCapture::captureScreen(&sc); sc->checkPixel(1, 1, Color::GREEN.r, Color::GREEN.g, Color::GREEN.b); } // Background layer (RED) // Foregroud layer (GREEN) // Child layer (BLUE) Transaction{}.reparent(childLayer, mForegroundLayer).apply(); { // The relative z info for child layer should be reset, leaving the child layer on top. ScreenCapture::captureScreen(&sc); sc->checkPixel(1, 1, Color::BLUE.r, Color::BLUE.g, Color::BLUE.b); } } // Preserve the relative z order when a layer is reparented to a layer that's already offscreen TEST_F(RelativeZTest, LayerWithRelativeReparentedToOffscreen) { std::unique_ptr sc; Color testLayerColor = {255, 100, 0, 255}; // Background layer (RED) // Foregroud layer (GREEN) // child level 1a (testLayerColor) (relative to child level 2b) // child level 1b (WHITE) // child level 2a (BLUE) // child level 2b (BLACK) sp childLevel1a = createColorLayer("child level 1a", testLayerColor, mForegroundLayer.get()); sp childLevel1b = createColorLayer("child level 1b", Color::WHITE, mForegroundLayer.get()); sp childLevel2a = createColorLayer("child level 2a", Color::BLUE, childLevel1b.get()); sp childLevel2b = createColorLayer("child level 2b", Color::BLACK, childLevel1b.get()); Transaction{} .setRelativeLayer(childLevel1a, childLevel2b, 1) .show(childLevel1a) .show(childLevel1b) .show(childLevel2a) .show(childLevel2b) .apply(); { // The childLevel1a should be in front of childLevel2b. ScreenCapture::captureScreen(&sc); sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), testLayerColor); } // Background layer (RED) // Foregroud layer (GREEN) // child level 1a (testLayerColor) (relative to child level 2b) Transaction{}.reparent(childLevel1b, nullptr).apply(); // // Background layer (RED) // // Foregroud layer (GREEN) Transaction{}.reparent(childLevel1a, childLevel2a).apply(); { // The childLevel1a and childLevel1b are no longer on screen ScreenCapture::captureScreen(&sc); sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), Color::GREEN); } // Background layer (RED) // Foregroud layer (GREEN) // child level 1b (WHITE) // child level 2a (BLUE) // child level 1a (testLayerColor) (relative to child level 2b) // child level 2b (BLACK) Transaction{}.reparent(childLevel1b, mForegroundLayer).apply(); { // Nothing should change at this point since relative z info was preserved. ScreenCapture::captureScreen(&sc); sc->expectColor(Rect(0, 0, mDisplayWidth, mDisplayHeight), testLayerColor); } } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion"