Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 373ed37c authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix SurfaceControl#captureLayers when the layer is boundless"

parents fcdc7ad8 efc42e2b
Loading
Loading
Loading
Loading
+8 −7
Original line number Diff line number Diff line
@@ -713,6 +713,14 @@ public:

    Region debugGetVisibleRegionOnDefaultDisplay() const;

    /**
     * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
     * INVALID_RECT if the layer has no buffer and no crop.
     * A layer with an invalid buffer size and no crop is considered to be boundless. The layer
     * bounds are constrained by its parent bounds.
     */
    Rect getCroppedBufferSize(const Layer::State& s) const;

protected:
    // constant
    sp<SurfaceFlinger> mFlinger;
@@ -921,13 +929,6 @@ private:
                                       const LayerVector::Visitor& visitor);
    LayerVector makeChildrenTraversalList(LayerVector::StateSet stateSet,
                                          const std::vector<Layer*>& layersInTree);
    /**
     * Returns the cropped buffer size or the layer crop if the layer has no buffer. Return
     * INVALID_RECT if the layer has no buffer and no crop.
     * A layer with an invalid buffer size and no crop is considered to be boundless. The layer
     * bounds are constrained by its parent bounds.
     */
    Rect getCroppedBufferSize(const Layer::State& s) const;

    // Cached properties computed from drawing state
    // Effective transform taking into account parent transforms and any parent scaling.
+9 −2
Original line number Diff line number Diff line
@@ -5089,14 +5089,21 @@ status_t SurfaceFlinger::captureLayers(
            return PERMISSION_DENIED;
        }

        Rect parentSourceBounds = parent->getCroppedBufferSize(parent->getCurrentState());
        if (sourceCrop.width() <= 0) {
            crop.left = 0;
            crop.right = parent->getBufferSize(parent->getCurrentState()).getWidth();
            crop.right = parentSourceBounds.getWidth();
        }

        if (sourceCrop.height() <= 0) {
            crop.top = 0;
            crop.bottom = parent->getBufferSize(parent->getCurrentState()).getHeight();
            crop.bottom = parentSourceBounds.getHeight();
        }

        if (crop.isEmpty() || frameScale <= 0.0f) {
            // Error out if the layer has no source bounds (i.e. they are boundless) and a source
            // crop was not specified, or an invalid frame scale was provided.
            return BAD_VALUE;
        }
        reqWidth = crop.width() * frameScale;
        reqHeight = crop.height() * frameScale;
+1 −1
Original line number Diff line number Diff line
@@ -274,7 +274,7 @@ TEST_F(CredentialsTest, CaptureLayersTest) {
        sp<GraphicBuffer> outBuffer;
        return ScreenshotClient::captureLayers(mBGSurfaceControl->getHandle(),
                                               ui::Dataspace::V0_SRGB, ui::PixelFormat::RGBA_8888,
                                               Rect(), FRAME_SCALE, &outBuffer);
                                               Rect(0, 0, 1, 1), FRAME_SCALE, &outBuffer);
    };
    ASSERT_NO_FATAL_FAILURE(checkWithPrivileges<status_t>(condition, NO_ERROR, PERMISSION_DENIED));
}
+55 −0
Original line number Diff line number Diff line
@@ -1443,6 +1443,61 @@ TEST_F(ScreenCaptureTest, CaptureRelativeInTree) {
    mCapture->expectColor(Rect(0, 0, 9, 9), {100, 100, 100, 255});
}

TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithSourceCrop) {
    sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
    SurfaceComposerClient::Transaction().show(child).apply(true);

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    sp<GraphicBuffer> outBuffer;
    Rect sourceCrop(0, 0, 10, 10);
    ASSERT_EQ(NO_ERROR, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
    ScreenCapture sc(outBuffer);

    sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
}

TEST_F(ScreenCaptureTest, CaptureBoundedLayerWithoutSourceCrop) {
    sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
    Rect layerCrop(0, 0, 10, 10);
    SurfaceComposerClient::Transaction().setCrop_legacy(child, layerCrop).show(child).apply(true);

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    sp<GraphicBuffer> outBuffer;
    Rect sourceCrop = Rect();
    ASSERT_EQ(NO_ERROR, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
    ScreenCapture sc(outBuffer);

    sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
}

TEST_F(ScreenCaptureTest, CaptureBoundlessLayerWithoutSourceCropFails) {
    sp<SurfaceControl> child = createColorLayer("Child layer", Color::RED, mFGSurfaceControl.get());
    SurfaceComposerClient::Transaction().show(child).apply(true);

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    sp<GraphicBuffer> outBuffer;
    Rect sourceCrop = Rect();

    ASSERT_EQ(BAD_VALUE, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
}

TEST_F(ScreenCaptureTest, CaptureBufferLayerWithoutBufferFails) {
    sp<SurfaceControl> child = createSurface(mClient, "Child surface", 10, 10,
                                             PIXEL_FORMAT_RGBA_8888, 0, mFGSurfaceControl.get());
    SurfaceComposerClient::Transaction().show(child).apply(true);

    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
    sp<GraphicBuffer> outBuffer;
    Rect sourceCrop = Rect();
    ASSERT_EQ(BAD_VALUE, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));

    TransactionUtils::fillSurfaceRGBA8(child, Color::RED);
    SurfaceComposerClient::Transaction().apply(true);
    ASSERT_EQ(NO_ERROR, sf->captureLayers(child->getHandle(), &outBuffer, sourceCrop));
    ScreenCapture sc(outBuffer);
    sc.expectColor(Rect(0, 0, 9, 9), 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.
+5 −0
Original line number Diff line number Diff line
@@ -136,6 +136,11 @@ public:
        }
    }

    static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, const Color& color,
                                 bool unlock = true) {
        fillSurfaceRGBA8(sc, color.r, color.g, color.b, unlock);
    }

    // Fill an RGBA_8888 formatted surface with a single color.
    static void fillSurfaceRGBA8(const sp<SurfaceControl>& sc, uint8_t r, uint8_t g, uint8_t b,
                                 bool unlock = true) {