Loading services/surfaceflinger/Layer.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -1453,6 +1453,13 @@ Layer::FrameRate Layer::getFrameRateForLayerTree() const { void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) { ATRACE_CALL(); if (mLayerDetached) { // If the layer is detached, then we don't defer this transaction since we will not // commit the pending state while the layer is detached. Adding sync points may cause // the barrier layer to wait for the states to be committed before dequeuing a buffer. return; } mCurrentState.barrierLayer_legacy = barrierLayer; mCurrentState.frameNumber_legacy = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral Loading services/surfaceflinger/tests/DetachChildren_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,58 @@ TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) { } } /** * Tests that a deferring transaction on an already detached layer will be dropped gracefully and * allow the barrier layer to dequeue buffers. * * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer * to commit its pending states. */ TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) { Color childColor = {200, 200, 200, 255}; Rect childBounds = Rect(74, 74, 84, 84); sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; sp<SurfaceControl> childNewClient = createSurface(newComposerClient, "New Child Test Surface", childBounds.width(), childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); ASSERT_TRUE(childNewClient->isValid()); TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor); Transaction() .show(childNewClient) .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left, childBounds.top - mMainSurfaceBounds.top) .apply(); { mCapture = screenshot(); mCapture->expectBorder(childBounds, mMainSurfaceColor); mCapture->expectColor(childBounds, childColor); } Transaction().detachChildren(mMainSurface).apply(); Transaction() .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()}) .deferTransactionUntil_legacy(childNewClient, mMainSurface->getHandle(), mMainSurface->getSurface()->getNextFrameNumber()) .apply(); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED, mMainSurfaceBounds.width(), mMainSurfaceBounds.height())); // BufferLayer can still dequeue buffers even though there's a detached layer with a // deferred transaction. { SCOPED_TRACE("new buffer"); mCapture = screenshot(); mCapture->expectBorder(childBounds, Color::RED); mCapture->expectColor(childBounds, childColor); } } TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) { Color childColor = {200, 200, 200, 255}; Rect childBounds = Rect(74, 74, 94, 94); Loading Loading
services/surfaceflinger/Layer.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -1453,6 +1453,13 @@ Layer::FrameRate Layer::getFrameRateForLayerTree() const { void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) { ATRACE_CALL(); if (mLayerDetached) { // If the layer is detached, then we don't defer this transaction since we will not // commit the pending state while the layer is detached. Adding sync points may cause // the barrier layer to wait for the states to be committed before dequeuing a buffer. return; } mCurrentState.barrierLayer_legacy = barrierLayer; mCurrentState.frameNumber_legacy = frameNumber; // We don't set eTransactionNeeded, because just receiving a deferral Loading
services/surfaceflinger/tests/DetachChildren_test.cpp +52 −0 Original line number Diff line number Diff line Loading @@ -256,6 +256,58 @@ TEST_F(DetachChildren, DetachChildrenWithDeferredTransaction) { } } /** * Tests that a deferring transaction on an already detached layer will be dropped gracefully and * allow the barrier layer to dequeue buffers. * * Fixes b/150924737 - buffer cannot be latched because it waits for a detached layer * to commit its pending states. */ TEST_F(DetachChildren, DeferredTransactionOnDetachedChildren) { Color childColor = {200, 200, 200, 255}; Rect childBounds = Rect(74, 74, 84, 84); sp<SurfaceComposerClient> newComposerClient = new SurfaceComposerClient; sp<SurfaceControl> childNewClient = createSurface(newComposerClient, "New Child Test Surface", childBounds.width(), childBounds.height(), PIXEL_FORMAT_RGBA_8888, 0, mMainSurface.get()); ASSERT_TRUE(childNewClient->isValid()); TransactionUtils::fillSurfaceRGBA8(childNewClient, childColor); Transaction() .show(childNewClient) .setPosition(childNewClient, childBounds.left - mMainSurfaceBounds.left, childBounds.top - mMainSurfaceBounds.top) .apply(); { mCapture = screenshot(); mCapture->expectBorder(childBounds, mMainSurfaceColor); mCapture->expectColor(childBounds, childColor); } Transaction().detachChildren(mMainSurface).apply(); Transaction() .setCrop_legacy(childNewClient, {0, 0, childBounds.width(), childBounds.height()}) .deferTransactionUntil_legacy(childNewClient, mMainSurface->getHandle(), mMainSurface->getSurface()->getNextFrameNumber()) .apply(); ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(mMainSurface, Color::RED, mMainSurfaceBounds.width(), mMainSurfaceBounds.height())); // BufferLayer can still dequeue buffers even though there's a detached layer with a // deferred transaction. { SCOPED_TRACE("new buffer"); mCapture = screenshot(); mCapture->expectBorder(childBounds, Color::RED); mCapture->expectColor(childBounds, childColor); } } TEST_F(DetachChildren, ReparentParentLayerOfDetachedChildren) { Color childColor = {200, 200, 200, 255}; Rect childBounds = Rect(74, 74, 94, 94); Loading