Skip to content

Commit

Permalink
Merge "Added new arguments for screenshot request" into sc-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Chavi Weingarten authored and Android (Google) Code Review committed Feb 1, 2021
2 parents 87eb2c4 + 17ac24b commit b89b51a
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 39 deletions.
8 changes: 6 additions & 2 deletions libs/gui/LayerState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -644,11 +644,13 @@ bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunc
status_t CaptureArgs::write(Parcel& output) const {
SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(pixelFormat));
SAFE_PARCEL(output.write, sourceCrop);
SAFE_PARCEL(output.writeFloat, frameScale);
SAFE_PARCEL(output.writeFloat, frameScaleX);
SAFE_PARCEL(output.writeFloat, frameScaleY);
SAFE_PARCEL(output.writeBool, captureSecureLayers);
SAFE_PARCEL(output.writeInt32, uid);
SAFE_PARCEL(output.writeInt32, static_cast<int32_t>(dataspace));
SAFE_PARCEL(output.writeBool, allowProtected);
SAFE_PARCEL(output.writeBool, grayscale);
return NO_ERROR;
}

Expand All @@ -657,12 +659,14 @@ status_t CaptureArgs::read(const Parcel& input) {
SAFE_PARCEL(input.readInt32, &value);
pixelFormat = static_cast<ui::PixelFormat>(value);
SAFE_PARCEL(input.read, sourceCrop);
SAFE_PARCEL(input.readFloat, &frameScale);
SAFE_PARCEL(input.readFloat, &frameScaleX);
SAFE_PARCEL(input.readFloat, &frameScaleY);
SAFE_PARCEL(input.readBool, &captureSecureLayers);
SAFE_PARCEL(input.readInt32, &uid);
SAFE_PARCEL(input.readInt32, &value);
dataspace = static_cast<ui::Dataspace>(value);
SAFE_PARCEL(input.readBool, &allowProtected);
SAFE_PARCEL(input.readBool, &grayscale);
return NO_ERROR;
}

Expand Down
5 changes: 4 additions & 1 deletion libs/gui/include/gui/LayerState.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,8 @@ struct CaptureArgs {

ui::PixelFormat pixelFormat{ui::PixelFormat::RGBA_8888};
Rect sourceCrop;
float frameScale{1};
float frameScaleX{1};
float frameScaleY{1};
bool captureSecureLayers{false};
int32_t uid{UNSET_UID};
// Force capture to be in a color space. If the value is ui::Dataspace::UNKNOWN, the captured
Expand All @@ -346,6 +347,8 @@ struct CaptureArgs {
// the contents being accessed/captured by screenshot or unsecure display.
bool allowProtected = false;

bool grayscale = false;

virtual status_t write(Parcel& output) const;
virtual status_t read(const Parcel& input);
};
Expand Down
2 changes: 1 addition & 1 deletion services/surfaceflinger/RegionSamplingThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ void RegionSamplingThread::captureSample() {

const sp<SyncScreenCaptureListener> captureListener = new SyncScreenCaptureListener();
mFlinger.captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
true /* regionSampling */, captureListener);
true /* regionSampling */, false /* grayscale */, captureListener);
ScreenCaptureResults captureResults = captureListener->waitForResults();

std::vector<Descriptor> activeDescriptors;
Expand Down
59 changes: 33 additions & 26 deletions services/surfaceflinger/SurfaceFlinger.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4909,23 +4909,24 @@ void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) co
result.append("\n");
}

void SurfaceFlinger::updateColorMatrixLocked() {
mat4 colorMatrix;
if (mGlobalSaturationFactor != 1.0f) {
// Rec.709 luma coefficients
float3 luminance{0.213f, 0.715f, 0.072f};
luminance *= 1.0f - mGlobalSaturationFactor;
mat4 saturationMatrix = mat4(
vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
vec4{0.0f, 0.0f, 0.0f, 1.0f}
);
colorMatrix = mClientColorMatrix * saturationMatrix * mDaltonizer();
} else {
colorMatrix = mClientColorMatrix * mDaltonizer();
mat4 SurfaceFlinger::calculateColorMatrix(float saturation) {
if (saturation == 1) {
return mat4();
}

float3 luminance{0.213f, 0.715f, 0.072f};
luminance *= 1.0f - saturation;
mat4 saturationMatrix = mat4(vec4{luminance.r + saturation, luminance.r, luminance.r, 0.0f},
vec4{luminance.g, luminance.g + saturation, luminance.g, 0.0f},
vec4{luminance.b, luminance.b, luminance.b + saturation, 0.0f},
vec4{0.0f, 0.0f, 0.0f, 1.0f});
return saturationMatrix;
}

void SurfaceFlinger::updateColorMatrixLocked() {
mat4 colorMatrix =
mClientColorMatrix * calculateColorMatrix(mGlobalSaturationFactor) * mDaltonizer();

if (mCurrentState.colorMatrix != colorMatrix) {
mCurrentState.colorMatrix = colorMatrix;
mCurrentState.colorMatrixChanged = true;
Expand Down Expand Up @@ -5637,7 +5638,8 @@ status_t SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args,
};

return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
args.pixelFormat, args.allowProtected, captureListener);
args.pixelFormat, args.allowProtected, args.grayscale,
captureListener);
}

status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack,
Expand Down Expand Up @@ -5673,7 +5675,7 @@ status_t SurfaceFlinger::captureDisplay(uint64_t displayOrLayerStack,

return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, size,
ui::PixelFormat::RGBA_8888, false /* allowProtected */,
captureListener);
false /* grayscale */, captureListener);
}

status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
Expand Down Expand Up @@ -5719,12 +5721,12 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
crop.bottom = parentSourceBounds.getHeight();
}

if (crop.isEmpty() || args.frameScale <= 0.0f) {
if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 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;
}
reqSize = ui::Size(crop.width() * args.frameScale, crop.height() * args.frameScale);
reqSize = ui::Size(crop.width() * args.frameScaleX, crop.height() * args.frameScaleY);

for (const auto& handle : args.excludeHandles) {
sp<Layer> excludeLayer = fromHandleLocked(handle).promote();
Expand Down Expand Up @@ -5794,13 +5796,14 @@ status_t SurfaceFlinger::captureLayers(const LayerCaptureArgs& args,
};

return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, reqSize,
args.pixelFormat, args.allowProtected, captureListener);
args.pixelFormat, args.allowProtected, args.grayscale,
captureListener);
}

status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
ui::Size bufferSize, ui::PixelFormat reqPixelFormat,
const bool allowProtected,
bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();

Expand Down Expand Up @@ -5831,12 +5834,13 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
static_cast<android_pixel_format>(reqPixelFormat),
1 /* layerCount */, usage, "screenshot");
return captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer,
false /* regionSampling */, captureListener);
false /* regionSampling */, grayscale, captureListener);
}

status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
TraverseLayersFunction traverseLayers,
sp<GraphicBuffer>& buffer, const bool regionSampling,
sp<GraphicBuffer>& buffer, bool regionSampling,
bool grayscale,
const sp<IScreenCaptureListener>& captureListener) {
ATRACE_CALL();

Expand All @@ -5852,7 +5856,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
if (mRefreshPending) {
ALOGW("Skipping screenshot for now");
captureScreenCommon(std::move(renderAreaFuture), traverseLayers, buffer, regionSampling,
captureListener);
grayscale, captureListener);
return;
}
ScreenCaptureResults captureResults;
Expand All @@ -5867,7 +5871,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
status_t result = NO_ERROR;
renderArea->render([&] {
result = renderScreenImplLocked(*renderArea, traverseLayers, buffer, forSystem,
regionSampling, captureResults);
regionSampling, grayscale, captureResults);
});

captureResults.result = result;
Expand All @@ -5880,7 +5884,7 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture,
status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
const sp<GraphicBuffer>& buffer, bool forSystem,
bool regionSampling,
bool regionSampling, bool grayscale,
ScreenCaptureResults& captureResults) {
ATRACE_CALL();

Expand Down Expand Up @@ -5921,6 +5925,9 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea,
clientCompositionDisplay.outputDataspace = renderArea.getReqDataSpace();
clientCompositionDisplay.maxLuminance = DisplayDevice::sDefaultMaxLumiance;

const float colorSaturation = grayscale ? 0 : 1;
clientCompositionDisplay.colorTransform = calculateColorMatrix(colorSaturation);

const float alpha = RenderArea::getCaptureFillValue(renderArea.getCaptureFill());

compositionengine::LayerFE::LayerSettings fillLayer;
Expand Down
9 changes: 6 additions & 3 deletions services/surfaceflinger/SurfaceFlinger.h
Original file line number Diff line number Diff line change
Expand Up @@ -810,13 +810,14 @@ class SurfaceFlinger : public BnSurfaceComposer,
void startBootAnim();

status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, ui::Size bufferSize,
ui::PixelFormat, const bool allowProtected,
ui::PixelFormat, bool allowProtected, bool grayscale,
const sp<IScreenCaptureListener>&);
status_t captureScreenCommon(RenderAreaFuture, TraverseLayersFunction, sp<GraphicBuffer>&,
bool regionSampling, const sp<IScreenCaptureListener>&);
bool regionSampling, bool grayscale,
const sp<IScreenCaptureListener>&);
status_t renderScreenImplLocked(const RenderArea&, TraverseLayersFunction,
const sp<GraphicBuffer>&, bool forSystem, bool regionSampling,
ScreenCaptureResults&);
bool grayscale, ScreenCaptureResults&);

sp<DisplayDevice> getDisplayByIdOrLayerStack(uint64_t displayOrLayerStack) REQUIRES(mStateLock);
sp<DisplayDevice> getDisplayByLayerStack(uint64_t layerStack) REQUIRES(mStateLock);
Expand Down Expand Up @@ -1019,6 +1020,8 @@ class SurfaceFlinger : public BnSurfaceComposer,

void onFrameRateFlexibilityTokenReleased();

static mat4 calculateColorMatrix(float saturation);

void updateColorMatrixLocked();

// Verify that transaction is being called by an approved process:
Expand Down
16 changes: 12 additions & 4 deletions services/surfaceflinger/tests/LayerState_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ TEST(LayerStateTest, ParcellingDisplayCaptureArgs) {
DisplayCaptureArgs args;
args.pixelFormat = ui::PixelFormat::RGB_565;
args.sourceCrop = Rect(0, 0, 500, 200);
args.frameScale = 2;
args.frameScaleX = 2;
args.frameScaleY = 4;
args.captureSecureLayers = true;
args.displayToken = new BBinder();
args.width = 10;
args.height = 20;
args.useIdentityTransform = true;
args.grayscale = true;

Parcel p;
args.write(p);
Expand All @@ -46,23 +48,27 @@ TEST(LayerStateTest, ParcellingDisplayCaptureArgs) {

ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
ASSERT_EQ(args.frameScale, args2.frameScale);
ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
ASSERT_EQ(args.displayToken, args2.displayToken);
ASSERT_EQ(args.width, args2.width);
ASSERT_EQ(args.height, args2.height);
ASSERT_EQ(args.useIdentityTransform, args2.useIdentityTransform);
ASSERT_EQ(args.grayscale, args2.grayscale);
}

TEST(LayerStateTest, ParcellingLayerCaptureArgs) {
LayerCaptureArgs args;
args.pixelFormat = ui::PixelFormat::RGB_565;
args.sourceCrop = Rect(0, 0, 500, 200);
args.frameScale = 2;
args.frameScaleX = 2;
args.frameScaleY = 4;
args.captureSecureLayers = true;
args.layerHandle = new BBinder();
args.excludeHandles = {new BBinder(), new BBinder()};
args.childrenOnly = false;
args.grayscale = true;

Parcel p;
args.write(p);
Expand All @@ -73,11 +79,13 @@ TEST(LayerStateTest, ParcellingLayerCaptureArgs) {

ASSERT_EQ(args.pixelFormat, args2.pixelFormat);
ASSERT_EQ(args.sourceCrop, args2.sourceCrop);
ASSERT_EQ(args.frameScale, args2.frameScale);
ASSERT_EQ(args.frameScaleX, args2.frameScaleX);
ASSERT_EQ(args.frameScaleY, args2.frameScaleY);
ASSERT_EQ(args.captureSecureLayers, args2.captureSecureLayers);
ASSERT_EQ(args.layerHandle, args2.layerHandle);
ASSERT_EQ(args.excludeHandles, args2.excludeHandles);
ASSERT_EQ(args.childrenOnly, args2.childrenOnly);
ASSERT_EQ(args.grayscale, args2.grayscale);
}

TEST(LayerStateTest, ParcellingScreenCaptureResults) {
Expand Down
39 changes: 38 additions & 1 deletion services/surfaceflinger/tests/ScreenCapture_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,9 @@ TEST_F(ScreenCaptureTest, CaptureSize) {
// red area to the right of the blue area
mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);

captureArgs.frameScale = 0.5f;
captureArgs.frameScaleX = 0.5f;
captureArgs.frameScaleY = 0.5f;

ScreenCapture::captureLayers(&mCapture, captureArgs);
// Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
mCapture->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
Expand Down Expand Up @@ -768,6 +770,41 @@ TEST_F(ScreenCaptureTest, CaptureLayerWithUid) {
mCapture->expectBorder(Rect(128, 128, 160, 160), {63, 63, 195, 255});
}

TEST_F(ScreenCaptureTest, CaptureWithGrayscale) {
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).setLayer(layer, INT32_MAX).apply();

LayerCaptureArgs captureArgs;
captureArgs.layerHandle = layer->getHandle();

ScreenCapture::captureLayers(&mCapture, captureArgs);
mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);

captureArgs.grayscale = true;

const uint8_t tolerance = 1;

// Values based on SurfaceFlinger::calculateColorMatrix
float3 luminance{0.213f, 0.715f, 0.072f};

ScreenCapture::captureLayers(&mCapture, captureArgs);

uint8_t expectedColor = luminance.r * 255;
mCapture->expectColor(Rect(0, 0, 32, 32),
Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);

ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLUE, 32, 32));
ScreenCapture::captureLayers(&mCapture, captureArgs);

expectedColor = luminance.b * 255;
mCapture->expectColor(Rect(0, 0, 32, 32),
Color{expectedColor, expectedColor, expectedColor, 255}, tolerance);
}

// 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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ class TestableSurfaceFlinger final : private ISchedulerCallback {
bool regionSampling) {
ScreenCaptureResults captureResults;
return mFlinger->renderScreenImplLocked(renderArea, traverseLayers, buffer, forSystem,
regionSampling, captureResults);
regionSampling, false /* grayscale */,
captureResults);
}

auto traverseLayersInLayerStack(ui::LayerStack layerStack, int32_t uid,
Expand Down

0 comments on commit b89b51a

Please sign in to comment.