Loading services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -175,7 +175,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te LayerFE::ClientCompositionTargetSettings targetSettings{ .clip = Region(viewport), .needsFiltering = false, .isSecure = true, .isSecure = outputState.isSecure, .supportsProtectedContent = false, .clearRegion = clearRegion, .viewport = viewport, Loading services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +69 −3 Original line number Diff line number Diff line Loading @@ -51,6 +51,15 @@ MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "" return expectedBlurSetting == arg.blurSetting; } MATCHER_P(ClientCompositionTargetSettingsSecureEq, expectedSecureSetting, "") { *result_listener << "ClientCompositionTargetSettings' SecureSettings aren't equal \n"; *result_listener << "expected " << expectedSecureSetting << "\n"; *result_listener << "actual " << arg.isSecure << "\n"; return expectedSecureSetting == arg.isSecure; } static const ui::Size kOutputSize = ui::Size(1, 1); class CachedSetTest : public testing::Test { Loading Loading @@ -315,7 +324,7 @@ TEST_F(CachedSetTest, updateAge_BufferUpdate) { EXPECT_EQ(0u, cachedSet.getAge()); } TEST_F(CachedSetTest, render) { TEST_F(CachedSetTest, renderUnsecureOutput) { // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; Loading Loading @@ -348,9 +357,66 @@ TEST_F(CachedSetTest, render) { return NO_ERROR; }; EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); EXPECT_CALL(*layerFE1, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(false))) .WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(false))) .WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = false; cachedSet.render(mRenderEngine, mTexturePool, mOutputState); expectReadyBuffer(cachedSet); EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds()); // Now check that appending a new cached set properly cleans up RenderEngine resources. CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } TEST_F(CachedSetTest, renderSecureOutput) { // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get(); sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE; CachedSet cachedSet(layer1); cachedSet.append(CachedSet(layer2)); std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1; clientCompList1.push_back({}); clientCompList1[0].alpha = 0.5f; std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2; clientCompList2.push_back({}); clientCompList2[0].alpha = 0.75f; const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, const std::vector<const renderengine::LayerSettings*>& layers, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, base::unique_fd&&, base::unique_fd*) -> size_t { EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), displaySettings.orientation); EXPECT_EQ(0.5f, layers[0]->alpha); EXPECT_EQ(0.75f, layers[1]->alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return NO_ERROR; }; EXPECT_CALL(*layerFE1, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(true))) .WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(true))) .WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = true; cachedSet.render(mRenderEngine, mTexturePool, mOutputState); expectReadyBuffer(cachedSet); Loading services/surfaceflinger/SurfaceFlinger.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -3382,7 +3382,7 @@ void SurfaceFlinger::invalidateHwcGeometry() { status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc, const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer, bool addToCurrentState, const sp<Layer>& parentLayer, bool addToRoot, uint32_t* outTransformHint) { if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) { ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(), Loading @@ -3394,7 +3394,7 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBind if (gbc != nullptr) { initialProducer = IInterface::asBinder(gbc); } setLayerCreatedState(handle, lbc, parentHandle, parentLayer, initialProducer); setLayerCreatedState(handle, lbc, parentHandle, parentLayer, initialProducer, addToRoot); // Create a transaction includes the initial parent and producer. Vector<ComposerState> states; Loading Loading @@ -3918,7 +3918,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( sp<Layer> layer = nullptr; if (s.surface) { if (what & layer_state_t::eLayerCreated) { layer = handleLayerCreatedLocked(s.surface, privileged); layer = handleLayerCreatedLocked(s.surface); if (layer) { // put the created layer into mLayersByLocalBinderToken. mLayersByLocalBinderToken.emplace(s.surface->localBinder(), layer); Loading Loading @@ -4328,9 +4328,9 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& clie return result; } bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess(); result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToCurrentState, outTransformHint); bool addToRoot = callingThreadHasUnscopedSurfaceFlingerAccess(); result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToRoot, outTransformHint); if (result != NO_ERROR) { return result; } Loading Loading @@ -6873,10 +6873,10 @@ void SurfaceFlinger::TransactionState::traverseStatesWithBuffers( void SurfaceFlinger::setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer, const wp<IBinder>& parent, const wp<Layer> parentLayer, const wp<IBinder>& producer) { const wp<IBinder>& producer, bool addToRoot) { Mutex::Autolock lock(mCreatedLayersLock); mCreatedLayers[handle->localBinder()] = std::make_unique<LayerCreatedState>(layer, parent, parentLayer, producer); std::make_unique<LayerCreatedState>(layer, parent, parentLayer, producer, addToRoot); } auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) { Loading @@ -6901,7 +6901,7 @@ auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) { return state; } sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle, bool privileged) { sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle) { const auto& state = getLayerCreatedState(handle); if (!state) { return nullptr; Loading @@ -6914,7 +6914,7 @@ sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle, bo } sp<Layer> parent; bool allowAddRoot = privileged; bool allowAddRoot = state->addToRoot; if (state->initialParent != nullptr) { parent = fromHandleLocked(state->initialParent.promote()).promote(); if (parent == nullptr) { Loading services/surfaceflinger/SurfaceFlinger.h +10 −6 Original line number Diff line number Diff line Loading @@ -905,7 +905,7 @@ private: status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc, const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer, bool addToCurrentState, uint32_t* outTransformHint); bool addToRoot, uint32_t* outTransformHint); // Traverse through all the layers and compute and cache its bounds. void computeLayerBounds(); Loading Loading @@ -1454,11 +1454,12 @@ private: mutable Mutex mCreatedLayersLock; struct LayerCreatedState { LayerCreatedState(const wp<Layer>& layer, const wp<IBinder>& parent, const wp<Layer> parentLayer, const wp<IBinder>& producer) const wp<Layer> parentLayer, const wp<IBinder>& producer, bool addToRoot) : layer(layer), initialParent(parent), initialParentLayer(parentLayer), initialProducer(producer) {} initialProducer(producer), addToRoot(addToRoot) {} wp<Layer> layer; // Indicates the initial parent of the created layer, only used for creating layer in // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers. Loading @@ -1467,6 +1468,10 @@ private: // Indicates the initial graphic buffer producer of the created layer, only used for // creating layer in SurfaceFlinger. wp<IBinder> initialProducer; // Indicates whether the layer getting created should be added at root if there's no parent // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will // be added offscreen. bool addToRoot; }; // A temporay pool that store the created layers and will be added to current state in main Loading @@ -1474,10 +1479,9 @@ private: std::unordered_map<BBinder*, std::unique_ptr<LayerCreatedState>> mCreatedLayers; void setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer, const wp<IBinder>& parent, const wp<Layer> parentLayer, const wp<IBinder>& producer); const wp<IBinder>& producer, bool addToRoot); auto getLayerCreatedState(const sp<IBinder>& handle); sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle, bool privileged) REQUIRES(mStateLock); sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle) REQUIRES(mStateLock); std::atomic<ui::Transform::RotationFlags> mDefaultDisplayTransformHint; Loading services/surfaceflinger/tests/MirrorLayer_test.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #include <private/android_filesystem_config.h> #include "LayerTransactionTest.h" #include "utils/TransactionUtils.h" namespace android { Loading Loading @@ -227,6 +229,50 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { } } // Test that the mirror layer is initially offscreen. TEST_F(MirrorLayerTest, InitialMirrorState) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ui::DisplayMode mode; SurfaceComposerClient::getActiveDisplayMode(display, &mode); const ui::Size& size = mode.resolution; sp<SurfaceControl> mirrorLayer = nullptr; { // Run as system to get the ACCESS_SURFACE_FLINGER permission when mirroring UIDFaker f(AID_SYSTEM); // Mirror mChildLayer mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); ASSERT_NE(mirrorLayer, nullptr); } // Show the mirror layer, but don't reparent to a layer on screen. Transaction() .setPosition(mirrorLayer, 500, 500) .show(mirrorLayer) .setLayer(mirrorLayer, INT32_MAX - 1) .apply(); { SCOPED_TRACE("Offscreen Mirror"); auto shot = screenshot(); shot->expectColor(Rect(0, 0, size.getWidth(), 50), Color::RED); shot->expectColor(Rect(0, 0, 50, size.getHeight()), Color::RED); shot->expectColor(Rect(450, 0, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(0, 450, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(50, 50, 450, 450), Color::GREEN); } // Add mirrorLayer as child of mParentLayer so it's shown on the display Transaction().reparent(mirrorLayer, mParentLayer).apply(); { SCOPED_TRACE("On Screen Mirror"); auto shot = screenshot(); // Child mirror shot->expectColor(Rect(550, 550, 950, 950), Color::GREEN); } } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues Loading Loading
services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -175,7 +175,7 @@ void CachedSet::render(renderengine::RenderEngine& renderEngine, TexturePool& te LayerFE::ClientCompositionTargetSettings targetSettings{ .clip = Region(viewport), .needsFiltering = false, .isSecure = true, .isSecure = outputState.isSecure, .supportsProtectedContent = false, .clearRegion = clearRegion, .viewport = viewport, Loading
services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +69 −3 Original line number Diff line number Diff line Loading @@ -51,6 +51,15 @@ MATCHER_P(ClientCompositionTargetSettingsBlurSettingsEq, expectedBlurSetting, "" return expectedBlurSetting == arg.blurSetting; } MATCHER_P(ClientCompositionTargetSettingsSecureEq, expectedSecureSetting, "") { *result_listener << "ClientCompositionTargetSettings' SecureSettings aren't equal \n"; *result_listener << "expected " << expectedSecureSetting << "\n"; *result_listener << "actual " << arg.isSecure << "\n"; return expectedSecureSetting == arg.isSecure; } static const ui::Size kOutputSize = ui::Size(1, 1); class CachedSetTest : public testing::Test { Loading Loading @@ -315,7 +324,7 @@ TEST_F(CachedSetTest, updateAge_BufferUpdate) { EXPECT_EQ(0u, cachedSet.getAge()); } TEST_F(CachedSetTest, render) { TEST_F(CachedSetTest, renderUnsecureOutput) { // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; Loading Loading @@ -348,9 +357,66 @@ TEST_F(CachedSetTest, render) { return NO_ERROR; }; EXPECT_CALL(*layerFE1, prepareClientCompositionList(_)).WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(_)).WillOnce(Return(clientCompList2)); EXPECT_CALL(*layerFE1, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(false))) .WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(false))) .WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = false; cachedSet.render(mRenderEngine, mTexturePool, mOutputState); expectReadyBuffer(cachedSet); EXPECT_EQ(mOutputState.framebufferSpace, cachedSet.getOutputSpace()); EXPECT_EQ(Rect(kOutputSize.width, kOutputSize.height), cachedSet.getTextureBounds()); // Now check that appending a new cached set properly cleans up RenderEngine resources. CachedSet::Layer& layer3 = *mTestLayers[2]->cachedSetLayer.get(); cachedSet.append(CachedSet(layer3)); } TEST_F(CachedSetTest, renderSecureOutput) { // Skip the 0th layer to ensure that the bounding box of the layers is offset from (0, 0) CachedSet::Layer& layer1 = *mTestLayers[1]->cachedSetLayer.get(); sp<mock::LayerFE> layerFE1 = mTestLayers[1]->layerFE; CachedSet::Layer& layer2 = *mTestLayers[2]->cachedSetLayer.get(); sp<mock::LayerFE> layerFE2 = mTestLayers[2]->layerFE; CachedSet cachedSet(layer1); cachedSet.append(CachedSet(layer2)); std::vector<compositionengine::LayerFE::LayerSettings> clientCompList1; clientCompList1.push_back({}); clientCompList1[0].alpha = 0.5f; std::vector<compositionengine::LayerFE::LayerSettings> clientCompList2; clientCompList2.push_back({}); clientCompList2[0].alpha = 0.75f; const auto drawLayers = [&](const renderengine::DisplaySettings& displaySettings, const std::vector<const renderengine::LayerSettings*>& layers, const std::shared_ptr<renderengine::ExternalTexture>&, const bool, base::unique_fd&&, base::unique_fd*) -> size_t { EXPECT_EQ(mOutputState.framebufferSpace.content, displaySettings.physicalDisplay); EXPECT_EQ(mOutputState.layerStackSpace.content, displaySettings.clip); EXPECT_EQ(ui::Transform::toRotationFlags(mOutputState.framebufferSpace.orientation), displaySettings.orientation); EXPECT_EQ(0.5f, layers[0]->alpha); EXPECT_EQ(0.75f, layers[1]->alpha); EXPECT_EQ(ui::Dataspace::SRGB, displaySettings.outputDataspace); return NO_ERROR; }; EXPECT_CALL(*layerFE1, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(true))) .WillOnce(Return(clientCompList1)); EXPECT_CALL(*layerFE2, prepareClientCompositionList(ClientCompositionTargetSettingsSecureEq(true))) .WillOnce(Return(clientCompList2)); EXPECT_CALL(mRenderEngine, drawLayers(_, _, _, _, _, _)).WillOnce(Invoke(drawLayers)); mOutputState.isSecure = true; cachedSet.render(mRenderEngine, mTexturePool, mOutputState); expectReadyBuffer(cachedSet); Loading
services/surfaceflinger/SurfaceFlinger.cpp +10 −10 Original line number Diff line number Diff line Loading @@ -3382,7 +3382,7 @@ void SurfaceFlinger::invalidateHwcGeometry() { status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc, const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer, bool addToCurrentState, const sp<Layer>& parentLayer, bool addToRoot, uint32_t* outTransformHint) { if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) { ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(), Loading @@ -3394,7 +3394,7 @@ status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBind if (gbc != nullptr) { initialProducer = IInterface::asBinder(gbc); } setLayerCreatedState(handle, lbc, parentHandle, parentLayer, initialProducer); setLayerCreatedState(handle, lbc, parentHandle, parentLayer, initialProducer, addToRoot); // Create a transaction includes the initial parent and producer. Vector<ComposerState> states; Loading Loading @@ -3918,7 +3918,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( sp<Layer> layer = nullptr; if (s.surface) { if (what & layer_state_t::eLayerCreated) { layer = handleLayerCreatedLocked(s.surface, privileged); layer = handleLayerCreatedLocked(s.surface); if (layer) { // put the created layer into mLayersByLocalBinderToken. mLayersByLocalBinderToken.emplace(s.surface->localBinder(), layer); Loading Loading @@ -4328,9 +4328,9 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& clie return result; } bool addToCurrentState = callingThreadHasUnscopedSurfaceFlingerAccess(); result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToCurrentState, outTransformHint); bool addToRoot = callingThreadHasUnscopedSurfaceFlingerAccess(); result = addClientLayer(client, *handle, *gbp, layer, parentHandle, parentLayer, addToRoot, outTransformHint); if (result != NO_ERROR) { return result; } Loading Loading @@ -6873,10 +6873,10 @@ void SurfaceFlinger::TransactionState::traverseStatesWithBuffers( void SurfaceFlinger::setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer, const wp<IBinder>& parent, const wp<Layer> parentLayer, const wp<IBinder>& producer) { const wp<IBinder>& producer, bool addToRoot) { Mutex::Autolock lock(mCreatedLayersLock); mCreatedLayers[handle->localBinder()] = std::make_unique<LayerCreatedState>(layer, parent, parentLayer, producer); std::make_unique<LayerCreatedState>(layer, parent, parentLayer, producer, addToRoot); } auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) { Loading @@ -6901,7 +6901,7 @@ auto SurfaceFlinger::getLayerCreatedState(const sp<IBinder>& handle) { return state; } sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle, bool privileged) { sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle) { const auto& state = getLayerCreatedState(handle); if (!state) { return nullptr; Loading @@ -6914,7 +6914,7 @@ sp<Layer> SurfaceFlinger::handleLayerCreatedLocked(const sp<IBinder>& handle, bo } sp<Layer> parent; bool allowAddRoot = privileged; bool allowAddRoot = state->addToRoot; if (state->initialParent != nullptr) { parent = fromHandleLocked(state->initialParent.promote()).promote(); if (parent == nullptr) { Loading
services/surfaceflinger/SurfaceFlinger.h +10 −6 Original line number Diff line number Diff line Loading @@ -905,7 +905,7 @@ private: status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, const sp<Layer>& lbc, const sp<IBinder>& parentHandle, const sp<Layer>& parentLayer, bool addToCurrentState, uint32_t* outTransformHint); bool addToRoot, uint32_t* outTransformHint); // Traverse through all the layers and compute and cache its bounds. void computeLayerBounds(); Loading Loading @@ -1454,11 +1454,12 @@ private: mutable Mutex mCreatedLayersLock; struct LayerCreatedState { LayerCreatedState(const wp<Layer>& layer, const wp<IBinder>& parent, const wp<Layer> parentLayer, const wp<IBinder>& producer) const wp<Layer> parentLayer, const wp<IBinder>& producer, bool addToRoot) : layer(layer), initialParent(parent), initialParentLayer(parentLayer), initialProducer(producer) {} initialProducer(producer), addToRoot(addToRoot) {} wp<Layer> layer; // Indicates the initial parent of the created layer, only used for creating layer in // SurfaceFlinger. If nullptr, it may add the created layer into the current root layers. Loading @@ -1467,6 +1468,10 @@ private: // Indicates the initial graphic buffer producer of the created layer, only used for // creating layer in SurfaceFlinger. wp<IBinder> initialProducer; // Indicates whether the layer getting created should be added at root if there's no parent // and has permission ACCESS_SURFACE_FLINGER. If set to false and no parent, the layer will // be added offscreen. bool addToRoot; }; // A temporay pool that store the created layers and will be added to current state in main Loading @@ -1474,10 +1479,9 @@ private: std::unordered_map<BBinder*, std::unique_ptr<LayerCreatedState>> mCreatedLayers; void setLayerCreatedState(const sp<IBinder>& handle, const wp<Layer>& layer, const wp<IBinder>& parent, const wp<Layer> parentLayer, const wp<IBinder>& producer); const wp<IBinder>& producer, bool addToRoot); auto getLayerCreatedState(const sp<IBinder>& handle); sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle, bool privileged) REQUIRES(mStateLock); sp<Layer> handleLayerCreatedLocked(const sp<IBinder>& handle) REQUIRES(mStateLock); std::atomic<ui::Transform::RotationFlags> mDefaultDisplayTransformHint; Loading
services/surfaceflinger/tests/MirrorLayer_test.cpp +46 −0 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" #include <private/android_filesystem_config.h> #include "LayerTransactionTest.h" #include "utils/TransactionUtils.h" namespace android { Loading Loading @@ -227,6 +229,50 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { } } // Test that the mirror layer is initially offscreen. TEST_F(MirrorLayerTest, InitialMirrorState) { const auto display = SurfaceComposerClient::getInternalDisplayToken(); ui::DisplayMode mode; SurfaceComposerClient::getActiveDisplayMode(display, &mode); const ui::Size& size = mode.resolution; sp<SurfaceControl> mirrorLayer = nullptr; { // Run as system to get the ACCESS_SURFACE_FLINGER permission when mirroring UIDFaker f(AID_SYSTEM); // Mirror mChildLayer mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); ASSERT_NE(mirrorLayer, nullptr); } // Show the mirror layer, but don't reparent to a layer on screen. Transaction() .setPosition(mirrorLayer, 500, 500) .show(mirrorLayer) .setLayer(mirrorLayer, INT32_MAX - 1) .apply(); { SCOPED_TRACE("Offscreen Mirror"); auto shot = screenshot(); shot->expectColor(Rect(0, 0, size.getWidth(), 50), Color::RED); shot->expectColor(Rect(0, 0, 50, size.getHeight()), Color::RED); shot->expectColor(Rect(450, 0, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(0, 450, size.getWidth(), size.getHeight()), Color::RED); shot->expectColor(Rect(50, 50, 450, 450), Color::GREEN); } // Add mirrorLayer as child of mParentLayer so it's shown on the display Transaction().reparent(mirrorLayer, mParentLayer).apply(); { SCOPED_TRACE("On Screen Mirror"); auto shot = screenshot(); // Child mirror shot->expectColor(Rect(550, 550, 950, 950), Color::GREEN); } } } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues Loading