Revert "Use GraphicBuffer instead of GBP for screenshots."
This reverts commit a252d895816b3aa6c3bc2b2083113694ead6963d.
Reason for revert: SystemUI and some other places need to be updated as well. Will resubmit with the other necessary changes
Change-Id: I2dfb7b439c866f31ffa584e450d3208c75afecaa
Bug: 69898957
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 5de84ec..c21c5e3 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -100,13 +100,17 @@
remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
}
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation) {
+ virtual status_t captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform,
+ ISurfaceComposer::Rotation rotation)
+ {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(display);
+ data.writeStrongBinder(IInterface::asBinder(producer));
data.write(sourceCrop);
data.writeUint32(reqWidth);
data.writeUint32(reqHeight);
@@ -114,45 +118,21 @@
data.writeInt32(maxLayerZ);
data.writeInt32(static_cast<int32_t>(useIdentityTransform));
data.writeInt32(static_cast<int32_t>(rotation));
- status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
-
- if (err != NO_ERROR) {
- return err;
- }
-
- err = reply.readInt32();
- if (err != NO_ERROR) {
- return err;
- }
-
- *outBuffer = new GraphicBuffer();
- reply.read(**outBuffer);
- return err;
+ remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
+ return reply.readInt32();
}
virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
- sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale) {
+ const sp<IGraphicBufferProducer>& producer,
+ const Rect& sourceCrop, float frameScale) {
Parcel data, reply;
data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
data.writeStrongBinder(layerHandleBinder);
+ data.writeStrongBinder(IInterface::asBinder(producer));
data.write(sourceCrop);
data.writeFloat(frameScale);
- status_t err = remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
-
- if (err != NO_ERROR) {
- return err;
- }
-
- err = reply.readInt32();
- if (err != NO_ERROR) {
- return err;
- }
-
- *outBuffer = new GraphicBuffer();
- reply.read(**outBuffer);
-
- return err;
+ remote()->transact(BnSurfaceComposer::CAPTURE_LAYERS, data, &reply);
+ return reply.readInt32();
}
virtual bool authenticateSurfaceTexture(
@@ -603,7 +583,8 @@
case CAPTURE_SCREEN: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> display = data.readStrongBinder();
- sp<GraphicBuffer> outBuffer;
+ sp<IGraphicBufferProducer> producer =
+ interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Rect sourceCrop(Rect::EMPTY_RECT);
data.read(sourceCrop);
uint32_t reqWidth = data.readUint32();
@@ -613,28 +594,24 @@
bool useIdentityTransform = static_cast<bool>(data.readInt32());
int32_t rotation = data.readInt32();
- status_t res = captureScreen(display, &outBuffer, sourceCrop, reqWidth, reqHeight,
- minLayerZ, maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ status_t res = captureScreen(display, producer,
+ sourceCrop, reqWidth, reqHeight, minLayerZ, maxLayerZ,
+ useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
reply->writeInt32(res);
- if (res == NO_ERROR) {
- reply->write(*outBuffer);
- }
return NO_ERROR;
}
case CAPTURE_LAYERS: {
CHECK_INTERFACE(ISurfaceComposer, data, reply);
sp<IBinder> layerHandleBinder = data.readStrongBinder();
- sp<GraphicBuffer> outBuffer;
+ sp<IGraphicBufferProducer> producer =
+ interface_cast<IGraphicBufferProducer>(data.readStrongBinder());
Rect sourceCrop(Rect::EMPTY_RECT);
data.read(sourceCrop);
float frameScale = data.readFloat();
- status_t res = captureLayers(layerHandleBinder, &outBuffer, sourceCrop, frameScale);
+ status_t res = captureLayers(layerHandleBinder, producer, sourceCrop, frameScale);
reply->writeInt32(res);
- if (res == NO_ERROR) {
- reply->write(*outBuffer);
- }
return NO_ERROR;
}
case AUTHENTICATE_SURFACE: {
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 80216bc..e939383 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -1760,25 +1760,4 @@
return OK;
}
-status_t Surface::attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer) {
- if (buffer == nullptr) {
- return BAD_VALUE;
- }
- int err = static_cast<ANativeWindow*>(surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
- NATIVE_WINDOW_API_CPU);
- if (err != OK) {
- return err;
- }
- err = surface->attachBuffer(buffer->getNativeBuffer());
- if (err != OK) {
- return err;
- }
- err = static_cast<ANativeWindow*>(surface)->queueBuffer(surface, buffer->getNativeBuffer(), -1);
- if (err != OK) {
- return err;
- }
- err = surface->disconnect(NATIVE_WINDOW_API_CPU);
- return err;
-}
-
}; // namespace android
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 0dbe786..2466d25 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -717,27 +717,181 @@
// ----------------------------------------------------------------------------
-status_t ScreenshotClient::capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
- uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, uint32_t rotation,
- sp<GraphicBuffer>* outBuffer) {
+status_t ScreenshotClient::capture(
+ const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
- status_t ret = s->captureScreen(display, outBuffer, sourceCrop, reqWidth, reqHeight, minLayerZ,
- maxLayerZ, useIdentityTransform,
- static_cast<ISurfaceComposer::Rotation>(rotation));
+ return s->captureScreen(display, producer, sourceCrop,
+ reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform);
+}
+
+status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
+ uint32_t rotation,
+ 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->captureScreen(display, producer, sourceCrop, reqWidth, reqHeight,
+ minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
if (ret != NO_ERROR) {
return ret;
}
+ BufferItem b;
+ consumer->acquireBuffer(&b, 0, true);
+ *outBuffer = b.mGraphicBuffer;
return ret;
}
-status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop,
- float frameScale, sp<GraphicBuffer>* outBuffer) {
+status_t ScreenshotClient::captureLayers(const sp<IBinder>& layerHandle,
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, float frameScale) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (s == NULL) return NO_INIT;
- status_t ret = s->captureLayers(layerHandle, outBuffer, sourceCrop, frameScale);
+ 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()
+ : mHaveBuffer(false) {
+ memset(&mBuffer, 0, sizeof(mBuffer));
+}
+
+ScreenshotClient::~ScreenshotClient() {
+ ScreenshotClient::release();
+}
+
+sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
+ if (mCpuConsumer == NULL) {
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&mProducer, &consumer);
+ mCpuConsumer = new CpuConsumer(consumer, 1);
+ mCpuConsumer->setName(String8("ScreenshotClient"));
+ }
+ return mCpuConsumer;
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation) {
+ sp<ISurfaceComposer> s(ComposerService::getComposerService());
+ if (s == NULL) return NO_INIT;
+ sp<CpuConsumer> cpuConsumer = getCpuConsumer();
+
+ if (mHaveBuffer) {
+ mCpuConsumer->unlockBuffer(mBuffer);
+ memset(&mBuffer, 0, sizeof(mBuffer));
+ mHaveBuffer = false;
+ }
+
+ status_t err = s->captureScreen(display, mProducer, sourceCrop,
+ reqWidth, reqHeight, minLayerZ, maxLayerZ, useIdentityTransform,
+ static_cast<ISurfaceComposer::Rotation>(rotation));
+
+ if (err == NO_ERROR) {
+ err = mCpuConsumer->lockNextBuffer(&mBuffer);
+ if (err == NO_ERROR) {
+ mHaveBuffer = true;
+ }
+ }
+ return err;
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform) {
+
+ return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
+ minLayerZ, maxLayerZ, useIdentityTransform, ISurfaceComposer::eRotateNone);
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
+ bool useIdentityTransform) {
+ return ScreenshotClient::update(display, sourceCrop, 0, 0,
+ INT32_MIN, INT32_MAX,
+ useIdentityTransform, ISurfaceComposer::eRotateNone);
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) {
+ return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight,
+ INT32_MIN, INT32_MAX,
+ useIdentityTransform, ISurfaceComposer::eRotateNone);
+}
+
+void ScreenshotClient::release() {
+ if (mHaveBuffer) {
+ mCpuConsumer->unlockBuffer(mBuffer);
+ memset(&mBuffer, 0, sizeof(mBuffer));
+ mHaveBuffer = false;
+ }
+ mCpuConsumer.clear();
+}
+
+void const* ScreenshotClient::getPixels() const {
+ return mBuffer.data;
+}
+
+uint32_t ScreenshotClient::getWidth() const {
+ return mBuffer.width;
+}
+
+uint32_t ScreenshotClient::getHeight() const {
+ return mBuffer.height;
+}
+
+PixelFormat ScreenshotClient::getFormat() const {
+ return mBuffer.format;
+}
+
+uint32_t ScreenshotClient::getStride() const {
+ return mBuffer.stride;
+}
+
+size_t ScreenshotClient::getSize() const {
+ return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
+}
+
+android_dataspace ScreenshotClient::getDataSpace() const {
+ return mBuffer.dataSpace;
+}
+
// ----------------------------------------------------------------------------
}; // namespace android
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index e26e332..1e4c329 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -29,7 +29,6 @@
#include <ui/FrameStats.h>
#include <ui/PixelFormat.h>
-#include <ui/GraphicBuffer.h>
#include <vector>
@@ -168,14 +167,16 @@
/* Capture the specified screen. requires READ_FRAME_BUFFER permission
* This function will fail if there is a secure window on screen.
*/
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- Rotation rotation = eRotateNone) = 0;
+ virtual status_t captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform,
+ Rotation rotation = eRotateNone) = 0;
virtual status_t captureLayers(const sp<IBinder>& layerHandleBinder,
- sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale = 1.0) = 0;
+ const sp<IGraphicBufferProducer>& producer,
+ const Rect& sourceCrop, float frameScale = 1.0) = 0;
/* Clears the frame statistics for animations.
*
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 354f23a..3fe29d9 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -283,8 +283,6 @@
android_dataspace_t getBuffersDataSpace();
- static status_t attachAndQueueBuffer(Surface* surface, sp<GraphicBuffer> buffer);
-
protected:
enum { NUM_BUFFER_SLOTS = BufferQueueDefs::NUM_BUFFER_SLOTS };
enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 3f13946..b0fa922 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -279,16 +279,74 @@
// ---------------------------------------------------------------------------
-class ScreenshotClient {
+class ScreenshotClient
+{
public:
// if cropping isn't required, callers may pass in a default Rect, e.g.:
// capture(display, producer, Rect(), reqWidth, ...);
- static status_t capture(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth,
- uint32_t reqHeight, int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform, uint32_t rotation,
- sp<GraphicBuffer>* outBuffer);
- static status_t captureLayers(const sp<IBinder>& layerHandle, Rect sourceCrop, float fameScale,
- sp<GraphicBuffer>* outBuffer);
+ static status_t capture(
+ const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform);
+ static status_t captureToBuffer(
+ const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform,
+ uint32_t rotation,
+ sp<GraphicBuffer>* outbuffer);
+
+ static status_t captureLayers(const sp<IBinder>& layerHandle,
+ 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;
+ mutable sp<IGraphicBufferProducer> mProducer;
+ CpuConsumer::LockedBuffer mBuffer;
+ bool mHaveBuffer;
+
+public:
+ ScreenshotClient();
+ ~ScreenshotClient();
+
+ // frees the previous screenshot and captures a new one
+ // if cropping isn't required, callers may pass in a default Rect, e.g.:
+ // update(display, Rect(), useIdentityTransform);
+ status_t update(const sp<IBinder>& display,
+ Rect sourceCrop, bool useIdentityTransform);
+ status_t update(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ bool useIdentityTransform);
+ status_t update(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform);
+ status_t update(const sp<IBinder>& display,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, uint32_t rotation);
+
+ sp<CpuConsumer> getCpuConsumer() const;
+
+ // release memory occupied by the screenshot
+ void release();
+
+ // pixels are valid until this object is freed or
+ // release() or update() is called
+ void const* getPixels() const;
+
+ uint32_t getWidth() const;
+ uint32_t getHeight() const;
+ PixelFormat getFormat() const;
+ uint32_t getStride() const;
+ // size of allocated memory in bytes
+ size_t getSize() const;
+ android_dataspace getDataSpace() const;
};
// ---------------------------------------------------------------------------
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 470a338..ac4eb0c 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -116,11 +116,14 @@
sp<ANativeWindow> anw(mSurface);
// Verify the screenshot works with no protected buffers.
+ 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));
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
64, 64, 0, 0x7fffffff, false));
ASSERT_EQ(NO_ERROR, native_window_api_connect(anw.get(),
@@ -151,7 +154,7 @@
&buf));
ASSERT_EQ(NO_ERROR, anw->queueBuffer(anw.get(), buf, -1));
}
- ASSERT_EQ(NO_ERROR, sf->captureScreen(display, &outBuffer, Rect(),
+ ASSERT_EQ(NO_ERROR, sf->captureScreen(display, producer, Rect(),
64, 64, 0, 0x7fffffff, false));
}
@@ -521,13 +524,13 @@
status_t setActiveColorMode(const sp<IBinder>& /*display*/,
android_color_mode_t /*colorMode*/) override { return NO_ERROR; }
status_t captureScreen(const sp<IBinder>& /*display*/,
- sp<GraphicBuffer>* /*outBuffer*/,
+ const sp<IGraphicBufferProducer>& /*producer*/,
Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/,
int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/,
bool /*useIdentityTransform*/,
Rotation /*rotation*/) override { return NO_ERROR; }
virtual status_t captureLayers(const sp<IBinder>& /*parentHandle*/,
- sp<GraphicBuffer>* /*outBuffer*/,
+ const sp<IGraphicBufferProducer>& /*producer*/,
const Rect& /*sourceCrop*/, float /*frameScale*/) override {
return NO_ERROR;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 4acd448..d81178c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4339,10 +4339,44 @@
const int mApi;
};
-status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ,
- bool useIdentityTransform,
+static status_t getWindowBuffer(ANativeWindow* window, uint32_t requestedWidth,
+ uint32_t requestedHeight, bool hasWideColorDisplay,
+ bool renderEngineUsesWideColor, ANativeWindowBuffer** outBuffer) {
+ const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
+ GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
+
+ int err = 0;
+ err = native_window_set_buffers_dimensions(window, requestedWidth, requestedHeight);
+ err |= native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
+ err |= native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888);
+ err |= native_window_set_usage(window, usage);
+
+ if (hasWideColorDisplay) {
+ err |= native_window_set_buffers_data_space(window,
+ renderEngineUsesWideColor
+ ? HAL_DATASPACE_DISPLAY_P3
+ : HAL_DATASPACE_V0_SRGB);
+ }
+
+ if (err != NO_ERROR) {
+ return BAD_VALUE;
+ }
+
+ /* TODO: Once we have the sync framework everywhere this can use
+ * server-side waits on the fence that dequeueBuffer returns.
+ */
+ err = native_window_dequeue_buffer_and_wait(window, outBuffer);
+ if (err != NO_ERROR) {
+ return err;
+ }
+
+ return NO_ERROR;
+}
+
+status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer, Rect sourceCrop,
+ uint32_t reqWidth, uint32_t reqHeight, int32_t minLayerZ,
+ int32_t maxLayerZ, bool useIdentityTransform,
ISurfaceComposer::Rotation rotation) {
ATRACE_CALL();
@@ -4353,18 +4387,18 @@
auto traverseLayers = std::bind(std::mem_fn(&SurfaceFlinger::traverseLayersInDisplay), this,
device, minLayerZ, maxLayerZ, std::placeholders::_1);
- return captureScreenCommon(renderArea, traverseLayers, outBuffer, useIdentityTransform);
+ return captureScreenCommon(renderArea, traverseLayers, producer, useIdentityTransform);
}
status_t SurfaceFlinger::captureLayers(const sp<IBinder>& layerHandleBinder,
- sp<GraphicBuffer>* outBuffer, const Rect& sourceCrop,
- float frameScale) {
+ const sp<IGraphicBufferProducer>& producer,
+ const Rect& sourceCrop, float frameScale) {
ATRACE_CALL();
class LayerRenderArea : public RenderArea {
public:
LayerRenderArea(const sp<Layer>& layer, const Rect crop, int32_t reqWidth,
- int32_t reqHeight)
+ 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
@@ -4427,21 +4461,51 @@
visitor(layer);
});
};
- return captureScreenCommon(renderArea, traverseLayers, outBuffer, false);
+ return captureScreenCommon(renderArea, traverseLayers, producer, false);
}
status_t SurfaceFlinger::captureScreenCommon(RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
- sp<GraphicBuffer>* outBuffer,
+ const sp<IGraphicBufferProducer>& producer,
bool useIdentityTransform) {
ATRACE_CALL();
+ if (CC_UNLIKELY(producer == 0))
+ return BAD_VALUE;
+
renderArea.updateDimensions();
- const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN |
- GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE;
- *outBuffer = new GraphicBuffer(renderArea.getReqWidth(), renderArea.getReqHeight(),
- HAL_PIXEL_FORMAT_RGBA_8888, 1, usage, "screenshot");
+ // if we have secure windows on this display, never allow the screen capture
+ // unless the producer interface is local (i.e.: we can take a screenshot for
+ // ourselves).
+ bool isLocalScreenshot = IInterface::asBinder(producer)->localBinder();
+
+ // create a surface (because we're a producer, and we need to
+ // dequeue/queue a buffer)
+ sp<Surface> surface = new Surface(producer, false);
+
+ // Put the screenshot Surface into async mode so that
+ // Layer::headFenceHasSignaled will always return true and we'll latch the
+ // first buffer regardless of whether or not its acquire fence has
+ // signaled. This is needed to avoid a race condition in the rotation
+ // animation. See b/30209608
+ surface->setAsyncMode(true);
+
+ ANativeWindow* window = surface.get();
+
+ status_t result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
+ if (result != NO_ERROR) {
+ return result;
+ }
+ WindowDisconnector disconnector(window, NATIVE_WINDOW_API_EGL);
+
+ ANativeWindowBuffer* buffer = nullptr;
+ result = getWindowBuffer(window, renderArea.getReqWidth(), renderArea.getReqHeight(),
+ hasWideColorDisplay && !mForceNativeColorMode,
+ getRenderEngine().usesWideColor(), &buffer);
+ if (result != NO_ERROR) {
+ return result;
+ }
// This mutex protects syncFd and captureResult for communication of the return values from the
// main thread back to this Binder thread
@@ -4466,8 +4530,8 @@
int fd = -1;
{
Mutex::Autolock _l(mStateLock);
- result = captureScreenImplLocked(renderArea, traverseLayers, (*outBuffer).get(),
- useIdentityTransform, &fd);
+ result = captureScreenImplLocked(renderArea, traverseLayers, buffer,
+ useIdentityTransform, isLocalScreenshot, &fd);
}
{
@@ -4478,7 +4542,7 @@
}
});
- status_t result = postMessageAsync(message);
+ result = postMessageAsync(message);
if (result == NO_ERROR) {
captureCondition.wait(captureLock, [&]() { return captureResult; });
while (*captureResult == EAGAIN) {
@@ -4493,10 +4557,9 @@
}
if (result == NO_ERROR) {
- sync_wait(syncFd, -1);
- close(syncFd);
+ // queueBuffer takes ownership of syncFd
+ result = window->queueBuffer(window, buffer, syncFd);
}
-
return result;
}
@@ -4539,8 +4602,7 @@
}
engine.setWideColor(renderArea.getWideColorSupport() && !mForceNativeColorMode);
- engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE
- : renderArea.getActiveColorMode());
+ engine.setColorMode(mForceNativeColorMode ? HAL_COLOR_MODE_NATIVE : renderArea.getActiveColorMode());
// make sure to clear all GL error flags
engine.checkErrors();
@@ -4583,7 +4645,7 @@
status_t SurfaceFlinger::captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer,
- bool useIdentityTransform,
+ bool useIdentityTransform, bool isLocalScreenshot,
int* outSyncFd) {
ATRACE_CALL();
@@ -4593,7 +4655,7 @@
secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && layer->isSecure());
});
- if (secureLayerIsVisible) {
+ if (!isLocalScreenshot && secureLayerIsVisible) {
ALOGW("FB is protected: PERMISSION_DENIED");
return PERMISSION_DENIED;
}
@@ -4742,4 +4804,4 @@
#if defined(__gl2_h_)
#error "don't include gl2/gl2.h in this file"
-#endif
\ No newline at end of file
+#endif
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a01d353..f61dc75 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -291,11 +291,13 @@
std::vector<FrameEvent>* outSupported) const;
virtual sp<IDisplayEventConnection> createDisplayEventConnection(
ISurfaceComposer::VsyncSource vsyncSource = eVsyncSourceApp);
- virtual status_t captureScreen(const sp<IBinder>& display, sp<GraphicBuffer>* outBuffer,
- Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
- int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform,
- ISurfaceComposer::Rotation rotation);
- virtual status_t captureLayers(const sp<IBinder>& parentHandle, sp<GraphicBuffer>* outBuffer,
+ virtual status_t captureScreen(const sp<IBinder>& display,
+ const sp<IGraphicBufferProducer>& producer,
+ Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight,
+ int32_t minLayerZ, int32_t maxLayerZ,
+ bool useIdentityTransform, ISurfaceComposer::Rotation rotation);
+ virtual status_t captureLayers(const sp<IBinder>& parentHandle,
+ const sp<IGraphicBufferProducer>& producer,
const Rect& sourceCrop, float frameScale);
virtual status_t getDisplayStats(const sp<IBinder>& display,
DisplayStatInfo* stats);
@@ -434,13 +436,15 @@
void renderScreenImplLocked(const RenderArea& renderArea, TraverseLayersFunction traverseLayers,
bool yswap, bool useIdentityTransform);
+
status_t captureScreenCommon(RenderArea& renderArea, TraverseLayersFunction traverseLayers,
- sp<GraphicBuffer>* outBuffer,
+ const sp<IGraphicBufferProducer>& producer,
bool useIdentityTransform);
+
status_t captureScreenImplLocked(const RenderArea& renderArea,
TraverseLayersFunction traverseLayers,
ANativeWindowBuffer* buffer, bool useIdentityTransform,
- int* outSyncFd);
+ bool isLocalScreenshot, int* outSyncFd);
void traverseLayersInDisplay(const sp<const DisplayDevice>& display, int32_t minLayerZ,
int32_t maxLayerZ, const LayerVector::Visitor& visitor);
diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp
index ff81dc9..39aef81 100644
--- a/services/surfaceflinger/tests/Transaction_test.cpp
+++ b/services/surfaceflinger/tests/Transaction_test.cpp
@@ -104,22 +104,20 @@
}
// Check if a region has the specified color.
-void expectBufferColor(const sp<GraphicBuffer>& outBuffer, uint8_t* pixels, const Rect& rect,
+void expectBufferColor(const CpuConsumer::LockedBuffer& buffer, const Rect& rect,
const Color& color, uint8_t tolerance) {
int32_t x = rect.left;
int32_t y = rect.top;
int32_t width = rect.right - rect.left;
int32_t height = rect.bottom - rect.top;
- int32_t bufferWidth = int32_t(outBuffer->getWidth());
- int32_t bufferHeight = int32_t(outBuffer->getHeight());
- if (x + width > bufferWidth) {
- x = std::min(x, bufferWidth);
- width = bufferWidth - x;
+ if (x + width > int32_t(buffer.width)) {
+ x = std::min(x, int32_t(buffer.width));
+ width = buffer.width - x;
}
- if (y + height > bufferHeight) {
- y = std::min(y, bufferHeight);
- height = bufferHeight - y;
+ if (y + height > int32_t(buffer.height)) {
+ y = std::min(y, int32_t(buffer.height));
+ height = buffer.height - y;
}
auto colorCompare = [tolerance](uint8_t a, uint8_t b) {
@@ -127,7 +125,8 @@
return tmp <= tolerance;
};
for (int32_t j = 0; j < height; j++) {
- const uint8_t* src = pixels + (outBuffer->getStride() * (y + j) + x) * 4;
+ const uint8_t* src =
+ static_cast<const uint8_t*>(buffer.data) + (buffer.stride * (y + j) + x) * 4;
for (int32_t i = 0; i < width; i++) {
const uint8_t expected[4] = {color.r, color.g, color.b, color.a};
EXPECT_TRUE(std::equal(src, src + 4, expected, colorCompare))
@@ -171,38 +170,30 @@
public:
static void captureScreen(sp<ScreenCapture>* sc, int32_t minLayerZ = 0,
int32_t maxLayerZ = std::numeric_limits<int32_t>::max()) {
+ 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);
- sp<GraphicBuffer> outBuffer;
ASSERT_EQ(NO_ERROR,
- sf->captureScreen(display, &outBuffer, Rect(), 0, 0, minLayerZ, maxLayerZ,
- false));
- *sc = new ScreenCapture(outBuffer);
- }
-
- static void captureLayers(std::unique_ptr<ScreenCapture>* sc, sp<IBinder>& parentHandle,
- Rect crop = Rect::EMPTY_RECT, float frameScale = 1.0) {
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- SurfaceComposerClient::Transaction().apply(true);
-
- sp<GraphicBuffer> outBuffer;
- ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, &outBuffer, crop, frameScale));
- *sc = std::make_unique<ScreenCapture>(outBuffer);
+ sf->captureScreen(display, producer, Rect(), 0, 0, minLayerZ, maxLayerZ, false));
+ *sc = new ScreenCapture(cpuConsumer);
}
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
- ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
- expectBufferColor(mOutBuffer, mPixels, rect, color, tolerance);
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
+ expectBufferColor(mBuf, rect, color, tolerance);
}
void expectBorder(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
- ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
const bool leftBorder = rect.left > 0;
const bool topBorder = rect.top > 0;
- const bool rightBorder = rect.right < int32_t(mOutBuffer->getWidth());
- const bool bottomBorder = rect.bottom < int32_t(mOutBuffer->getHeight());
+ const bool rightBorder = rect.right < int32_t(mBuf.width);
+ const bool bottomBorder = rect.bottom < int32_t(mBuf.height);
if (topBorder) {
Rect top(rect.left, rect.top - 1, rect.right, rect.top);
@@ -255,8 +246,9 @@
}
void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
- ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mOutBuffer->getPixelFormat());
- const uint8_t* pixel = mPixels + (4 * (y * mOutBuffer->getStride() + x));
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuf.format);
+ const uint8_t* img = static_cast<const uint8_t*>(mBuf.data);
+ const uint8_t* pixel = img + (4 * (y * mBuf.stride + x));
if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
String8 err(String8::format("pixel @ (%3d, %3d): "
"expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
@@ -271,15 +263,58 @@
void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
- ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
- mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
+private:
+ ScreenCapture(const sp<CpuConsumer>& cc) : mCC(cc) {
+ EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuf));
}
- ~ScreenCapture() { mOutBuffer->unlock(); }
+ ~ScreenCapture() { mCC->unlockBuffer(mBuf); }
+
+ sp<CpuConsumer> mCC;
+ CpuConsumer::LockedBuffer mBuf;
+};
+
+class CaptureLayer {
+public:
+ 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());
+ SurfaceComposerClient::Transaction().apply(true);
+ ASSERT_EQ(NO_ERROR, sf->captureLayers(parentHandle, producer, crop, frameScale));
+ *sc = std::make_unique<CaptureLayer>(cpuConsumer);
+ }
+
+ void checkPixel(uint32_t x, uint32_t y, uint8_t r, uint8_t g, uint8_t b) {
+ ASSERT_EQ(HAL_PIXEL_FORMAT_RGBA_8888, mBuffer.format);
+ const uint8_t* img = static_cast<const uint8_t*>(mBuffer.data);
+ const uint8_t* pixel = img + (4 * (y * mBuffer.stride + x));
+ if (r != pixel[0] || g != pixel[1] || b != pixel[2]) {
+ String8 err(String8::format("pixel @ (%3d, %3d): "
+ "expected [%3d, %3d, %3d], got [%3d, %3d, %3d]",
+ x, y, r, g, b, pixel[0], pixel[1], pixel[2]));
+ EXPECT_EQ(String8(), err) << err.string();
+ }
+ }
+
+ void expectFGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 195, 63, 63); }
+
+ void expectBGColor(uint32_t x, uint32_t y) { checkPixel(x, y, 63, 63, 195); }
+
+ void expectChildColor(uint32_t x, uint32_t y) { checkPixel(x, y, 200, 200, 200); }
+
+ CaptureLayer(const sp<CpuConsumer>& cc) : mCC(cc) {
+ EXPECT_EQ(NO_ERROR, mCC->lockNextBuffer(&mBuffer));
+ }
+
+ ~CaptureLayer() { mCC->unlockBuffer(mBuffer); }
private:
- sp<GraphicBuffer> mOutBuffer;
- uint8_t* mPixels = NULL;
+ sp<CpuConsumer> mCC;
+ CpuConsumer::LockedBuffer mBuffer;
};
class LayerTransactionTest : public ::testing::Test {
@@ -823,17 +858,21 @@
ASSERT_NO_FATAL_FAILURE(fillLayerColor(layer, Color::RED));
sp<ISurfaceComposer> composer = ComposerService::getComposerService();
- sp<GraphicBuffer> outBuffer;
+ sp<IGraphicBufferProducer> producer;
+ sp<IGraphicBufferConsumer> consumer;
+ BufferQueue::createBufferQueue(&producer, &consumer);
+ sp<CpuConsumer> cpuConsumer = new CpuConsumer(consumer, 1);
+
Transaction()
.setFlags(layer, layer_state_t::eLayerSecure, layer_state_t::eLayerSecure)
.apply(true);
ASSERT_EQ(PERMISSION_DENIED,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
+ composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
false));
Transaction().setFlags(layer, 0, layer_state_t::eLayerSecure).apply(true);
ASSERT_EQ(NO_ERROR,
- composer->captureScreen(mDisplay, &outBuffer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
+ composer->captureScreen(mDisplay, producer, Rect(), 0, 0, mLayerZBase, mLayerZBase,
false));
}
@@ -1465,7 +1504,7 @@
}
}
-class LayerUpdateTest : public LayerTransactionTest {
+class LayerUpdateTest : public ::testing::Test {
protected:
virtual void SetUp() {
mComposerClient = new SurfaceComposerClient;
@@ -2279,12 +2318,12 @@
class ScreenCaptureTest : public LayerUpdateTest {
protected:
- std::unique_ptr<ScreenCapture> mCapture;
+ std::unique_ptr<CaptureLayer> mCapture;
};
TEST_F(ScreenCaptureTest, CaptureSingleLayer) {
auto bgHandle = mBGSurfaceControl->getHandle();
- ScreenCapture::captureLayers(&mCapture, bgHandle);
+ CaptureLayer::captureScreen(&mCapture, bgHandle);
mCapture->expectBGColor(0, 0);
// Doesn't capture FG layer which is at 64, 64
mCapture->expectBGColor(64, 64);
@@ -2301,7 +2340,7 @@
SurfaceComposerClient::Transaction().show(child).apply(true);
// Captures mFGSurfaceControl layer and its child.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
+ CaptureLayer::captureScreen(&mCapture, fgHandle);
mCapture->expectFGColor(10, 10);
mCapture->expectChildColor(0, 0);
}
@@ -2326,7 +2365,7 @@
.apply(true);
// Captures mFGSurfaceControl, its child, and the grandchild.
- ScreenCapture::captureLayers(&mCapture, fgHandle);
+ CaptureLayer::captureScreen(&mCapture, fgHandle);
mCapture->expectFGColor(10, 10);
mCapture->expectChildColor(0, 0);
mCapture->checkPixel(5, 5, 50, 50, 50);
@@ -2342,7 +2381,7 @@
SurfaceComposerClient::Transaction().setPosition(child, 5, 5).show(child).apply(true);
// Captures only the child layer, and not the parent.
- ScreenCapture::captureLayers(&mCapture, childHandle);
+ CaptureLayer::captureScreen(&mCapture, childHandle);
mCapture->expectChildColor(0, 0);
mCapture->expectChildColor(9, 9);
}
@@ -2368,96 +2407,94 @@
auto grandchildHandle = grandchild->getHandle();
// Captures only the grandchild.
- ScreenCapture::captureLayers(&mCapture, grandchildHandle);
+ CaptureLayer::captureScreen(&mCapture, grandchildHandle);
mCapture->checkPixel(0, 0, 50, 50, 50);
mCapture->checkPixel(4, 4, 50, 50, 50);
}
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());
+ 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());
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+ fillSurfaceRGBA8(redLayer, 255, 0, 0);
+ fillSurfaceRGBA8(blueLayer, 0, 0, 255);
SurfaceComposerClient::Transaction()
- .setLayer(redLayer, INT32_MAX - 1)
- .show(redLayer)
- .show(blueLayer)
- .apply(true);
+ .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.
- ScreenCapture::captureLayers(&mCapture, redLayerHandle);
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+ 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);
- ScreenCapture::captureLayers(&mCapture, redLayerHandle, crop);
+ CaptureLayer::captureScreen(&mCapture, redLayerHandle, crop);
// Capturing the cropped screen, cropping out the shown red area, should leave only the blue
// area visible.
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
+ 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());
+ 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());
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(blueLayer, Color::BLUE));
+ fillSurfaceRGBA8(redLayer, 255, 0, 0);
+ fillSurfaceRGBA8(blueLayer, 0, 0, 255);
SurfaceComposerClient::Transaction()
- .setLayer(redLayer, INT32_MAX - 1)
- .show(redLayer)
- .show(blueLayer)
- .apply(true);
+ .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.
- ScreenCapture::captureLayers(&mCapture, redLayerHandle);
- mCapture->expectColor(Rect(0, 0, 29, 29), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 30, 59, 59), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(30, 0, 59, 59), Color::RED);
+ CaptureLayer::captureScreen(&mCapture, redLayerHandle);
+ mCapture->checkPixel(29, 29, 0, 0, 255);
+ mCapture->checkPixel(30, 30, 255, 0, 0);
- ScreenCapture::captureLayers(&mCapture, redLayerHandle, Rect::EMPTY_RECT, 0.5);
+ 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->expectColor(Rect(0, 0, 14, 14), Color::BLUE);
- // red area below the blue area
- mCapture->expectColor(Rect(0, 15, 29, 29), Color::RED);
- // red area to the right of the blue area
- mCapture->expectColor(Rect(15, 0, 29, 29), Color::RED);
+ 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);
+ sp<SurfaceControl> redLayer = mComposerClient->createSurface(
+ String8("Red surface"),
+ 60, 60, PIXEL_FORMAT_RGBA_8888, 0);
- ASSERT_NO_FATAL_FAILURE(fillLayerColor(redLayer, Color::RED));
+ fillSurfaceRGBA8(redLayer, 255, 0, 0);
auto redLayerHandle = redLayer->getHandle();
mComposerClient->destroySurface(redLayerHandle);
SurfaceComposerClient::Transaction().apply(true);
- sp<GraphicBuffer> outBuffer;
+ 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
- sp<ISurfaceComposer> sf(ComposerService::getComposerService());
- ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0));
+ ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, producer, Rect::EMPTY_RECT, 1.0));
}
-} // namespace android
+}
\ No newline at end of file