Merge "DO NOT MERGE: Move blast sync handling to BBQ" into sc-v2-dev
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index f559ed0..e2f34fa 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -421,8 +421,6 @@
 
     compositionState->blendMode = static_cast<Hwc2::IComposerClient::BlendMode>(blendMode);
     compositionState->alpha = alpha;
-    compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
-    compositionState->blurRegions = drawingState.blurRegions;
     compositionState->stretchEffect = getStretchEffect();
 }
 
@@ -498,6 +496,9 @@
         compositionState->stretchEffect.hasEffect()) {
         compositionState->forceClientComposition = true;
     }
+    // If there are no visible region changes, we still need to update blur parameters.
+    compositionState->blurRegions = drawingState.blurRegions;
+    compositionState->backgroundBlurRadius = drawingState.backgroundBlurRadius;
 }
 
 void Layer::prepareCursorCompositionState() {
@@ -938,8 +939,11 @@
 
 bool Layer::setBackgroundBlurRadius(int backgroundBlurRadius) {
     if (mDrawingState.backgroundBlurRadius == backgroundBlurRadius) return false;
-
-    mDrawingState.sequence++;
+    // If we start or stop drawing blur then the layer's visibility state may change so increment
+    // the magic sequence number.
+    if (mDrawingState.backgroundBlurRadius == 0 || backgroundBlurRadius == 0) {
+        mDrawingState.sequence++;
+    }
     mDrawingState.backgroundBlurRadius = backgroundBlurRadius;
     mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
@@ -972,6 +976,11 @@
 }
 
 bool Layer::setBlurRegions(const std::vector<BlurRegion>& blurRegions) {
+    // If we start or stop drawing blur then the layer's visibility state may change so increment
+    // the magic sequence number.
+    if (mDrawingState.blurRegions.size() == 0 || blurRegions.size() == 0) {
+        mDrawingState.sequence++;
+    }
     mDrawingState.blurRegions = blurRegions;
     mDrawingState.modified = true;
     setTransactionFlags(eTransactionNeeded);
diff --git a/services/surfaceflinger/LayerRenderArea.cpp b/services/surfaceflinger/LayerRenderArea.cpp
index e84508f..11fe6d0 100644
--- a/services/surfaceflinger/LayerRenderArea.cpp
+++ b/services/surfaceflinger/LayerRenderArea.cpp
@@ -94,8 +94,22 @@
     // no need to check rotation because there is none
     mNeedsFiltering = sourceCrop.width() != getReqWidth() || sourceCrop.height() != getReqHeight();
 
+    // If layer is offscreen, update mirroring info if it exists
+    if (mLayer->isRemovedFromCurrentState()) {
+        mLayer->traverse(LayerVector::StateSet::Drawing,
+                         [&](Layer* layer) { layer->updateMirrorInfo(); });
+        mLayer->traverse(LayerVector::StateSet::Drawing,
+                         [&](Layer* layer) { layer->updateCloneBufferInfo(); });
+    }
+
     if (!mChildrenOnly) {
         mTransform = mLayer->getTransform().inverse();
+        // If the layer is offscreen, compute bounds since we don't compute bounds for offscreen
+        // layers in a regular cycles.
+        if (mLayer->isRemovedFromCurrentState()) {
+            FloatRect maxBounds = mFlinger.getMaxDisplayBounds();
+            mLayer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */);
+        }
         drawLayers();
     } else {
         uint32_t w = static_cast<uint32_t>(getWidth());
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 29d35c2..758cc70 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2455,7 +2455,7 @@
     }
 }
 
-void SurfaceFlinger::computeLayerBounds() {
+FloatRect SurfaceFlinger::getMaxDisplayBounds() {
     // Find the largest width and height among all the displays.
     int32_t maxDisplayWidth = 0;
     int32_t maxDisplayHeight = 0;
@@ -2473,8 +2473,13 @@
 
     // Ignore display bounds for now since they will be computed later. Use a large Rect bound
     // to ensure it's bigger than an actual display will be.
-    FloatRect maxBounds(-maxDisplayWidth * 10, -maxDisplayHeight * 10, maxDisplayWidth * 10,
-                        maxDisplayHeight * 10);
+    FloatRect maxBounds = FloatRect(-maxDisplayWidth * 10, -maxDisplayHeight * 10,
+                                    maxDisplayWidth * 10, maxDisplayHeight * 10);
+    return maxBounds;
+}
+
+void SurfaceFlinger::computeLayerBounds() {
+    FloatRect maxBounds = getMaxDisplayBounds();
     for (const auto& layer : mDrawingState.layersSortedByZ) {
         layer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */);
     }
@@ -6167,9 +6172,7 @@
     sp<Layer> parent;
     Rect crop(args.sourceCrop);
     std::unordered_set<sp<Layer>, ISurfaceComposer::SpHash<Layer>> excludeLayers;
-    Rect layerStackSpaceRect;
     ui::Dataspace dataspace;
-    bool captureSecureLayers;
 
     // Call this before holding mStateLock to avoid any deadlocking.
     bool canCaptureBlackoutContent = hasCaptureBlackoutContentPermission();
@@ -6178,7 +6181,7 @@
         Mutex::Autolock lock(mStateLock);
 
         parent = fromHandle(args.layerHandle).promote();
-        if (parent == nullptr || parent->isRemovedFromCurrentState()) {
+        if (parent == nullptr) {
             ALOGE("captureLayers called with an invalid or removed parent");
             return NAME_NOT_FOUND;
         }
@@ -6217,39 +6220,36 @@
             }
         }
 
-        const auto display = findDisplay(WithLayerStack(parent->getLayerStack()));
-        if (!display) {
-            return NAME_NOT_FOUND;
-        }
-
-        layerStackSpaceRect = display->getLayerStackSpaceRect();
-
         // The dataspace is depended on the color mode of display, that could use non-native mode
         // (ex. displayP3) to enhance the content, but some cases are checking native RGB in bytes,
         // and failed if display is not in native mode. This provide a way to force using native
         // colors when capture.
         dataspace = args.dataspace;
         if (dataspace == ui::Dataspace::UNKNOWN) {
+            auto display = findDisplay(WithLayerStack(parent->getLayerStack()));
+            if (!display) {
+                // If the layer is not on a display, use the dataspace for the default display.
+                display = getDefaultDisplayDeviceLocked();
+            }
+
             const ui::ColorMode colorMode = display->getCompositionDisplay()->getState().colorMode;
             dataspace = pickDataspaceFromColorMode(colorMode);
         }
 
-        captureSecureLayers = args.captureSecureLayers && display->isSecure();
     } // mStateLock
 
     // really small crop or frameScale
-    if (reqSize.width <= 0) {
-        reqSize.width = 1;
-    }
-    if (reqSize.height <= 0) {
-        reqSize.height = 1;
+    if (reqSize.width <= 0 || reqSize.height <= 0) {
+        ALOGW("Failed to captureLayes: crop or scale too small");
+        return BAD_VALUE;
     }
 
+    Rect layerStackSpaceRect(0, 0, reqSize.width, reqSize.height);
     bool childrenOnly = args.childrenOnly;
     RenderAreaFuture renderAreaFuture = ftl::defer([=]() -> std::unique_ptr<RenderArea> {
         return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace,
                                                  childrenOnly, layerStackSpaceRect,
-                                                 captureSecureLayers);
+                                                 args.captureSecureLayers);
     });
 
     auto traverseLayers = [parent, args, excludeLayers](const LayerVector::Visitor& visitor) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 9e2e216..74fe7d9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -337,6 +337,7 @@
     // Disables expensive rendering for all displays
     // This is scheduled on the main thread
     void disableExpensiveRendering();
+    FloatRect getMaxDisplayBounds();
 
 protected:
     // We're reference counted, never destroy SurfaceFlinger directly
diff --git a/services/surfaceflinger/tests/InvalidHandles_test.cpp b/services/surfaceflinger/tests/InvalidHandles_test.cpp
index 9cf7c09..d192a2d 100644
--- a/services/surfaceflinger/tests/InvalidHandles_test.cpp
+++ b/services/surfaceflinger/tests/InvalidHandles_test.cpp
@@ -52,17 +52,6 @@
     }
 };
 
-TEST_F(InvalidHandleTest, createSurfaceInvalidParentHandle) {
-    // The createSurface is scheduled now, we could still get a created surface from createSurface.
-    // Should verify if it actually added into current state by checking the screenshot.
-    auto notSc = mScc->createSurface(String8("lolcats"), 19, 47, PIXEL_FORMAT_RGBA_8888, 0,
-                                     mNotSc->getHandle());
-    LayerCaptureArgs args;
-    args.layerHandle = notSc->getHandle();
-    ScreenCaptureResults captureResults;
-    ASSERT_EQ(NAME_NOT_FOUND, ScreenCapture::captureLayers(args, captureResults));
-}
-
 TEST_F(InvalidHandleTest, captureLayersInvalidHandle) {
     LayerCaptureArgs args;
     args.layerHandle = mNotSc->getHandle();
diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp
index d027865..b7a9271 100644
--- a/services/surfaceflinger/tests/MirrorLayer_test.cpp
+++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp
@@ -273,6 +273,61 @@
     }
 }
 
+// Test that a mirror layer can be screenshot when offscreen
+TEST_F(MirrorLayerTest, OffscreenMirrorScreenshot) {
+    const auto display = SurfaceComposerClient::getInternalDisplayToken();
+    ui::DisplayMode mode;
+    SurfaceComposerClient::getActiveDisplayMode(display, &mode);
+    const ui::Size& size = mode.resolution;
+
+    sp<SurfaceControl> grandchild =
+            createLayer("Grandchild layer", 50, 50, ISurfaceComposerClient::eFXSurfaceBufferState,
+                        mChildLayer.get());
+    ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(grandchild, Color::BLUE, 50, 50));
+    Rect childBounds = Rect(50, 50, 450, 450);
+
+    asTransaction([&](Transaction& t) {
+        t.setCrop(grandchild, Rect(0, 0, 50, 50)).show(grandchild);
+        t.setFlags(grandchild, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque);
+    });
+
+    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().show(mirrorLayer).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(100, 100, 450, 450), Color::GREEN);
+        shot->expectColor(Rect(50, 50, 100, 100), Color::BLUE);
+    }
+
+    {
+        SCOPED_TRACE("Capture Mirror");
+        // Capture just the mirror layer and child.
+        LayerCaptureArgs captureArgs;
+        captureArgs.layerHandle = mirrorLayer->getHandle();
+        captureArgs.sourceCrop = childBounds;
+        std::unique_ptr<ScreenCapture> shot;
+        ScreenCapture::captureLayers(&shot, captureArgs);
+        shot->expectSize(childBounds.width(), childBounds.height());
+        shot->expectColor(Rect(0, 0, 50, 50), Color::BLUE);
+        shot->expectColor(Rect(50, 50, 400, 400), Color::GREEN);
+    }
+}
+
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index ab2064e..2d5b502 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -37,6 +37,8 @@
         ASSERT_EQ(NO_ERROR, SurfaceComposerClient::getActiveDisplayMode(display, &mode));
         const ui::Size& resolution = mode.resolution;
 
+        mDisplaySize = resolution;
+
         // Background surface
         mBGSurfaceControl = createLayer(String8("BG Test Surface"), resolution.getWidth(),
                                         resolution.getHeight(), 0);
@@ -72,6 +74,7 @@
     sp<SurfaceControl> mBGSurfaceControl;
     sp<SurfaceControl> mFGSurfaceControl;
     std::unique_ptr<ScreenCapture> mCapture;
+    ui::Size mDisplaySize;
 };
 
 TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) {
@@ -515,18 +518,8 @@
 }
 
 TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
-    sp<SurfaceControl> redLayer = createLayer(String8("Red surface"), 60, 60,
-                                              ISurfaceComposerClient::eFXSurfaceBufferState);
-
-    ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(redLayer, Color::RED, 60, 60));
-
-    auto redLayerHandle = redLayer->getHandle();
-    Transaction().reparent(redLayer, nullptr).apply();
-    redLayer.clear();
-    SurfaceComposerClient::Transaction().apply(true);
-
     LayerCaptureArgs args;
-    args.layerHandle = redLayerHandle;
+    args.layerHandle = new BBinder();
 
     ScreenCaptureResults captureResults;
     // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
@@ -840,6 +833,33 @@
                           Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
 }
 
+TEST_F(ScreenCaptureTest, CaptureOffscreen) {
+    sp<SurfaceControl> layer;
+    ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
+                                                ISurfaceComposerClient::eFXSurfaceBufferState,
+                                                mBGSurfaceControl.get()));
+    ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::RED, 32, 32));
+
+    Transaction().show(layer).hide(mFGSurfaceControl).reparent(layer, nullptr).apply();
+
+    DisplayCaptureArgs displayCaptureArgs;
+    displayCaptureArgs.displayToken = mDisplay;
+
+    {
+        // Validate that the red layer is not on screen
+        ScreenCapture::captureDisplay(&mCapture, displayCaptureArgs);
+        mCapture->expectColor(Rect(0, 0, mDisplaySize.width, mDisplaySize.height),
+                              {63, 63, 195, 255});
+    }
+
+    LayerCaptureArgs captureArgs;
+    captureArgs.layerHandle = layer->getHandle();
+
+    ScreenCapture::captureLayers(&mCapture, captureArgs);
+    mCapture->expectSize(32, 32);
+    mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);
+}
+
 // In the following tests we verify successful skipping of a parent layer,
 // so we use the same verification logic and only change how we mutate
 // the parent layer to verify that various properties are ignored.
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index ddaa5a1..cae7684 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -175,6 +175,11 @@
 
     void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
 
+    void expectSize(uint32_t width, uint32_t height) {
+        EXPECT_EQ(width, mOutBuffer->getWidth());
+        EXPECT_EQ(height, mOutBuffer->getHeight());
+    }
+
     explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
         if (mOutBuffer) {
             mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));