|  | /* | 
|  | * 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<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, 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<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, 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<ScreenCapture> sc; | 
|  |  | 
|  | // Background layer (RED) | 
|  | // Foregroud layer (GREEN) | 
|  | //   Child layer (BLUE) (relative to relativeToLayer layer) | 
|  | //   Relative layer (WHITE) | 
|  | sp<SurfaceControl> childLayer = | 
|  | createColorLayer("Child layer", Color::BLUE, mForegroundLayer.get()); | 
|  | sp<SurfaceControl> 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<ScreenCapture> 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<SurfaceControl> childLevel1a = | 
|  | createColorLayer("child level 1a", testLayerColor, mForegroundLayer.get()); | 
|  | sp<SurfaceControl> childLevel1b = | 
|  | createColorLayer("child level 1b", Color::WHITE, mForegroundLayer.get()); | 
|  | sp<SurfaceControl> childLevel2a = | 
|  | createColorLayer("child level 2a", Color::BLUE, childLevel1b.get()); | 
|  | sp<SurfaceControl> 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" |