Add additional parameters for the captureLayer functions.

1. Added new captureLayers function that will return a GraphicBuffer
instead of storing into a Surface.
2. Added crop to captureLayers function.
3. Added frameScale to allow captures to scale.
4. Removed rotation parameter from captureLayers since it will always be
in the correct orientation.

Test: Transaction_test ScreenCaptureTest.CaptureCrop, .CaptureSize

Change-Id: Ib16d8575cf0c103126b9427ad32e2d28d568ea61
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 973302c..c21c5e3 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -124,12 +124,13 @@
 
     virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
                                    const sp<IGraphicBufferProducer>& producer,
-                                   ISurfaceComposer::Rotation rotation) {
+                                   const Rect& sourceCrop, float frameScale) {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
         data.writeStrongBinder(layerHandleBinder);
         data.writeStrongBinder(IInterface::asBinder(producer));
-        data.writeInt32(static_cast<int32_t>(rotation));
+        data.write(sourceCrop);
+        data.writeFloat(frameScale);
         remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
         return reply.readInt32();
     }
@@ -605,10 +606,11 @@
             sp<IBinder> layerHandleBinder = data.readStrongBinder();
             sp<IGraphicBufferProducer> producer =
                     interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
-            int32_t rotation = data.readInt32();
+            Rect sourceCrop(Rect::EMPTY_RECT);
+            data.read(sourceCrop);
+            float frameScale = data.readFloat();
 
-            status_t res = captureLayers(layerHandleBinder, producer,
-                                         static_cast<ISurfaceComposer::Rotation>(rotation));
+            status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale);
             reply->writeInt32(res);
             return NO_ERROR;
         }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 2adc273..2466d25 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -757,11 +757,34 @@
 
 status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle,
                                          const sp<IGraphicBufferProducer>& producer,
-                                         uint32_t rotation) {
+                                         Rect sourceCrop, float frameScale) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
-    return s->captureLayers(layerHandle, producer,
-                            static_cast<ISurfaceComposer::Rotation>(rotation));
+    return s->captureLayers(layerHandle, producer, sourceCrop, frameScale);
+}
+
+status_t ScreenshotClient::captureLayersToBuffer(const sp<IBinder>& layerHandle, Rect sourceCrop,
+                                                 float frameScale, sp<GraphicBuffer>* outBuffer) {
+    sp<ISurfaceComposer> s(ComposerService::getComposerService());
+    if (s == NULL) return NO_INIT;
+
+    sp<IGraphicBufferConsumer> gbpConsumer;
+    sp<IGraphicBufferProducer> producer;
+    BufferQueue::createBufferQueue(&producer, &gbpConsumer);
+    sp<BufferItemConsumer> consumer(new BufferItemConsumer(gbpConsumer,
+                                                           GRALLOC_USAGE_HW_TEXTURE |
+                                                                   GRALLOC_USAGE_SW_READ_NEVER |
+                                                                   GRALLOC_USAGE_SW_WRITE_NEVER,
+                                                           1, true));
+
+    status_t ret = s->captureLayers(layerHandle, producer, sourceCrop, frameScale);
+    if (ret != NO_ERROR) {
+        return ret;
+    }
+    BufferItem b;
+    consumer->acquireBuffer(&b, 0, true);
+    *outBuffer = b.mGraphicBuffer;
+    return ret;
 }
 
 ScreenshotClient::ScreenshotClient()
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 13e7473..1e4c329 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -176,7 +176,7 @@
 
     virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
                                    const sp<IGraphicBufferProducer>& producer,
-                                   Rotation rotation = eRotateNone) = 0;
+                                   const Rect& sourceCrop, float frameScale = 1.0) = 0;
 
     /* Clears the frame statistics for animations.
      *
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 87fdfae..b0fa922 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -297,8 +297,12 @@
             bool useIdentityTransform,
             uint32_t rotation,
             sp<GraphicBuffer>* outbuffer);
+
     static status_t captureLayers(const sp<IBinder>& layerHandle,
-                                  const sp<IGraphicBufferProducer>& producer, uint32_t rotation);
+                                  const sp<IGraphicBufferProducer>& producer, Rect sourceCrop,
+                                        float frameScale);
+    static status_t captureLayersToBuffer(const sp<IBinder>& layerHandle, Rect sourceCrop,
+                                          float frameScale, sp<GraphicBuffer>* outBuffer);
 
 private:
     mutable sp<CpuConsumer> mCpuConsumer;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 660680b..ac4eb0c 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -531,7 +531,7 @@
             Rotation /*rotation*/) override { return NO_ERROR; }
     virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
                                    const sp<IGraphicBufferProducer>& /*producer*/,
-                                   ISurfaceComposer::Rotation /*rotation*/) override {
+                                   const Rect& /*sourceCrop*/, float /*frameScale*/) override {
         return NO_ERROR;
     }
     status_t clearAnimationFrameStats() override { return NO_ERROR; }
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index 44b9dc9..fa4df83 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -6,7 +6,8 @@
 
 class RenderArea {
 public:
-    RenderArea(uint32_t reqHeight, uint32_t reqWidth, ISurfaceComposer::Rotation rotation)
+    RenderArea(uint32_t reqHeight, uint32_t reqWidth,
+               ISurfaceComposer::Rotation rotation = ISurfaceComposer::eRotateNone)
           : mReqHeight(reqHeight), mReqWidth(reqWidth) {
         mRotationFlags = Transform::fromRotation(rotation);
     }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index ec2a459..ea4f495 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4398,15 +4398,14 @@
 
 status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
                                        const sp<IGraphicBufferProducer>& producer,
-                                       ISurfaceComposer::Rotation rotation) {
+                                       const Rect& sourceCrop, float frameScale) {
     ATRACE_CALL();
 
     class LayerRenderArea : public RenderArea {
     public:
-        LayerRenderArea(const sp<Layer>& layer, ISurfaceComposer::Rotation rotation)
-              : RenderArea(layer->getCurrentState().active.h, layer->getCurrentState().active.w,
-                           rotation),
-                mLayer(layer) {}
+        LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth,
+            int32_t reqHeight)
+              : RenderArea(reqHeight, reqWidth), mLayer(layer), mCrop(crop) {}
         const Transform& getTransform() const override {
             // Make the top level transform the inverse the transform and it's parent so it sets
             // the whole capture back to 0,0
@@ -4421,18 +4420,45 @@
         bool isSecure() const override { return false; }
         bool needsFiltering() const override { return false; }
 
-        Rect getSourceCrop() const override { return getBounds(); }
+        Rect getSourceCrop() const override {
+            if (mCrop.isEmpty()) {
+                return getBounds();
+            } else {
+                return mCrop;
+            }
+        }
         bool getWideColorSupport() const override { return false; }
         android_color_mode_t getActiveColorMode() const override { return HAL_COLOR_MODE_NATIVE; }
 
     private:
-        const sp<Layer>& mLayer;
+        const sp<Layer> mLayer;
+        const Rect mCrop;
     };
 
     auto layerHandle = reinterpret_cast<Layer::Handle*>(layerHandleBinder.get());
     auto parent = layerHandle->owner.promote();
 
-    LayerRenderArea renderArea(parent, rotation);
+    if (parent == nullptr || parent->isPendingRemoval()) {
+        ALOGE("captureLayers called with a removed parent");
+        return NAME_NOT_FOUND;
+    }
+
+    Rect crop(sourceCrop);
+    if (sourceCrop.width() <= 0) {
+        crop.left = 0;
+        crop.right = parent->getCurrentState().active.w;
+    }
+
+    if (sourceCrop.height() <= 0) {
+        crop.top = 0;
+        crop.bottom = parent->getCurrentState().active.h;
+    }
+
+    int32_t reqWidth = crop.width() * frameScale;
+    int32_t reqHeight = crop.height() * frameScale;
+
+    LayerRenderArea renderArea(parent, crop, reqWidth, reqHeight);
+
     auto traverseLayers = [parent](const LayerVector::Visitor& visitor) {
         parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) {
             if (!layer->isVisible()) {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 386d42b..f61dc75 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -298,7 +298,7 @@
             bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
     virtual status_t captureLayers(const sp<IBinder>& parentHandle,
                                    const sp<IGraphicBufferProducer>& producer,
-                                   ISurfaceComposer::Rotation rotation);
+                                   const Rect& sourceCrop, float frameScale);
     virtual status_t getDisplayStats(const sp<IBinder>& display,
             DisplayStatInfo* stats);
     virtual status_t getDisplayConfigs(const sp<IBinder>& display,
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index 943fafd..39aef81 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -276,15 +276,15 @@
 
 class CaptureLayer {
 public:
-    static void captureScreen(std::unique_ptr<CaptureLayer>* sc, sp<IBinder>& parentHandle) {
+    static void captureScreen(std::unique_ptr<CaptureLayer>* sc, sp<IBinder>& parentHandle,
+                              Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
         sp<IGraphicBufferProducer> producer;
         sp<IGraphicBufferConsumer> consumer;
         BufferQueue::createBufferQueue(&producer, &consumer);
         sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
         sp<ISurfaceComposer> sf(ComposerService::getComposerService());
-        sp<IBinder> display(sf->getBuiltInDisplay(ISurfaceComposer::eDisplayIdMain));
         SurfaceComposerClient::Transaction().apply(true);
-        ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer));
+        ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale));
         *sc = std::make_unique<CaptureLayer>(cpuConsumer);
     }
 
@@ -2412,4 +2412,89 @@
     mCapture->checkPixel(4, 4, 50, 50, 50);
 }
 
-} // namespace android
+TEST_F(ScreenCaptureTest, CaptureCrop) {
+    sp<SurfaceControl> redLayer = mComposerClient->createSurface(
+        String8("Red surface"),
+        60, 60, PIXEL_FORMAT_RGBA_8888, 0);
+    sp<SurfaceControl> blueLayer = mComposerClient->createSurface(
+        String8("Blue surface"),
+        30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
+
+    fillSurfaceRGBA8(redLayer, 255, 0, 0);
+    fillSurfaceRGBA8(blueLayer, 0, 0, 255);
+
+    SurfaceComposerClient::Transaction()
+        .setLayer(redLayer, INT32_MAX-1)
+        .show(redLayer)
+        .show(blueLayer)
+        .apply(true);
+
+    auto redLayerHandle = redLayer->getHandle();
+
+    // Capturing full screen should have both red and blue are visible.
+    CaptureLayer::captureScreen(&mCapture, redLayerHandle);
+    mCapture->checkPixel(29, 29, 0, 0, 255);
+    mCapture->checkPixel(30, 30, 255, 0, 0);
+
+    Rect crop = Rect(0, 0, 30, 30);
+    CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop);
+    // Capturing the cropped screen, cropping out the shown red area, should leave only the blue
+    // area visible.
+    mCapture->checkPixel(29, 29, 0, 0, 255);
+    mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureSize) {
+    sp<SurfaceControl> redLayer = mComposerClient->createSurface(
+        String8("Red surface"),
+        60, 60, PIXEL_FORMAT_RGBA_8888, 0);
+    sp<SurfaceControl> blueLayer = mComposerClient->createSurface(
+        String8("Blue surface"),
+        30, 30, PIXEL_FORMAT_RGBA_8888, 0, redLayer.get());
+
+    fillSurfaceRGBA8(redLayer, 255, 0, 0);
+    fillSurfaceRGBA8(blueLayer, 0, 0, 255);
+
+    SurfaceComposerClient::Transaction()
+        .setLayer(redLayer, INT32_MAX-1)
+        .show(redLayer)
+        .show(blueLayer)
+        .apply(true);
+
+    auto redLayerHandle = redLayer->getHandle();
+
+    // Capturing full screen should have both red and blue are visible.
+    CaptureLayer::captureScreen(&mCapture, redLayerHandle);
+    mCapture->checkPixel(29, 29, 0, 0, 255);
+    mCapture->checkPixel(30, 30, 255, 0, 0);
+
+    CaptureLayer::captureScreen(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+    // Capturing the downsized area (30x30) should leave both red and blue but in a smaller area.
+    mCapture->checkPixel(14, 14, 0, 0, 255);
+    mCapture->checkPixel(15, 15, 255, 0, 0);
+    mCapture->checkPixel(29, 29, 255, 0, 0);
+    mCapture->checkPixel(30, 30, 0, 0, 0);
+}
+
+TEST_F(ScreenCaptureTest, CaptureInvalidLayer) {
+    sp<SurfaceControl> redLayer = mComposerClient->createSurface(
+        String8("Red surface"),
+        60, 60, PIXEL_FORMAT_RGBA_8888, 0);
+
+    fillSurfaceRGBA8(redLayer, 255, 0, 0);
+
+    auto redLayerHandle = redLayer->getHandle();
+    mComposerClient->destroySurface(redLayerHandle);
+    SurfaceComposerClient::Transaction().apply(true);
+
+    sp<IGraphicBufferProducer> producer;
+    sp<IGraphicBufferConsumer> consumer;
+    BufferQueue::createBufferQueue(&producer, &consumer);
+    sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+    sp<ISurfaceComposer> sf(ComposerService::getComposerService());
+
+    // Layer was deleted so captureLayers should fail with NAME_NOT_FOUND
+    ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0));
+}
+
+}
\ No newline at end of file