diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-22 01:08:00 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-07-22 01:08:00 +0000 |
commit | 3052ac2da7046e5cb825b94152f863a061e89856 (patch) | |
tree | d318514dfeb6c6dfbf1bf272aa2ab997162efb14 | |
parent | 853e2f90cc300a1f5a1c8331b7aa40a3cef89bc0 (diff) | |
parent | 5a68a6cfe076081a6bbdfb04cb85551d511539d9 (diff) | |
download | native-3052ac2da7046e5cb825b94152f863a061e89856.tar.gz |
Snap for 7571067 from 5a68a6cfe076081a6bbdfb04cb85551d511539d9 to sc-release
Change-Id: If9512e82699a4c70323c7c648443851454542e2f
5 files changed, 136 insertions, 20 deletions
diff --git a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp index b24274e731..f80ec223c1 100644 --- a/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp +++ b/services/surfaceflinger/CompositionEngine/src/planner/CachedSet.cpp @@ -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, diff --git a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp index b05a594a92..b765337410 100644 --- a/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/planner/CachedSetTest.cpp @@ -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 { @@ -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; @@ -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); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0b369a5d17..2cc810986f 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -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(), @@ -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; @@ -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); @@ -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; } @@ -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) { @@ -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; @@ -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) { diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b1fd208725..4fd86af24f 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -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(); @@ -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. @@ -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 @@ -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; diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index ccf434d63a..d02786504e 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -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 { @@ -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 |