rework how we take screenshots for a CPU consumer

We're not using IMemoryHeap as a transport anymore,
instead we're providing a CpuConsumer and use the
IGraphicBufferProducer version of the screenshot API.

However, some GPU drivers don't support properly
a GPU to CPU path, to work around this, we use a
temporary BufferQueue on the server side for the
GL rendering, and we use glReadPixels into the
CpuConsumer (we're now using a CPU to CPU path
which is always supported).

Currently this "wrapping" is always performed,
but it can be bypassed on devices that support
the GPU to CPU path.

This also addresses a DoS attack vector on
SurfaceFlinger, where an application could
consume all of SF's filedescriptors by creating
a lot of screenshots in a row.

Bug: 8390553

Change-Id: I9e81514c2a7711b9bb393f74305be7d2abe08f1c
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 0a79ff7..6442a86 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -102,31 +102,11 @@
         remote()->transact(BnSurfaceComposer::BOOT_FINISHED, data, &reply);
     }
 
-    virtual status_t captureScreen(
-            const sp<IBinder>& display, sp<IMemoryHeap>* heap,
-            uint32_t* width, uint32_t* height, PixelFormat* format,
-            uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ)
-    {
-        Parcel data, reply;
-        data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
-        data.writeStrongBinder(display);
-        data.writeInt32(reqWidth);
-        data.writeInt32(reqHeight);
-        data.writeInt32(minLayerZ);
-        data.writeInt32(maxLayerZ);
-        remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN_DEPRECATED, data, &reply);
-        *heap = interface_cast<IMemoryHeap>(reply.readStrongBinder());
-        *width = reply.readInt32();
-        *height = reply.readInt32();
-        *format = reply.readInt32();
-        return reply.readInt32();
-    }
-
     virtual status_t captureScreen(const sp<IBinder>& display,
             const sp<IGraphicBufferProducer>& producer,
             uint32_t reqWidth, uint32_t reqHeight,
-            uint32_t minLayerZ, uint32_t maxLayerZ)
+            uint32_t minLayerZ, uint32_t maxLayerZ,
+            bool isCpuConsumer)
     {
         Parcel data, reply;
         data.writeInterfaceToken(ISurfaceComposer::getInterfaceDescriptor());
@@ -136,6 +116,7 @@
         data.writeInt32(reqHeight);
         data.writeInt32(minLayerZ);
         data.writeInt32(maxLayerZ);
+        data.writeInt32(isCpuConsumer);
         remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply);
         return reply.readInt32();
     }
@@ -285,24 +266,6 @@
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             bootFinished();
         } break;
-        case CAPTURE_SCREEN_DEPRECATED: {
-            CHECK_INTERFACE(ISurfaceComposer, data, reply);
-            sp<IBinder> display = data.readStrongBinder();
-            uint32_t reqWidth = data.readInt32();
-            uint32_t reqHeight = data.readInt32();
-            uint32_t minLayerZ = data.readInt32();
-            uint32_t maxLayerZ = data.readInt32();
-            sp<IMemoryHeap> heap;
-            uint32_t w, h;
-            PixelFormat f;
-            status_t res = captureScreen(display, &heap, &w, &h, &f,
-                    reqWidth, reqHeight, minLayerZ, maxLayerZ);
-            reply->writeStrongBinder(heap->asBinder());
-            reply->writeInt32(w);
-            reply->writeInt32(h);
-            reply->writeInt32(f);
-            reply->writeInt32(res);
-        } break;
         case CAPTURE_SCREEN: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
             sp<IBinder> display = data.readStrongBinder();
@@ -312,8 +275,10 @@
             uint32_t reqHeight = data.readInt32();
             uint32_t minLayerZ = data.readInt32();
             uint32_t maxLayerZ = data.readInt32();
+            bool isCpuConsumer = data.readInt32();
             status_t res = captureScreen(display, producer,
-                    reqWidth, reqHeight, minLayerZ, maxLayerZ);
+                    reqWidth, reqHeight, minLayerZ, maxLayerZ,
+                    isCpuConsumer);
             reply->writeInt32(res);
         } break;
         case AUTHENTICATE_SURFACE: {
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 4a4c0c8..ec46fce 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -31,6 +31,7 @@
 
 #include <ui/DisplayInfo.h>
 
+#include <gui/CpuConsumer.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/ISurfaceComposer.h>
 #include <gui/ISurfaceComposerClient.h>
@@ -617,30 +618,21 @@
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
     return s->captureScreen(display, producer,
-            reqWidth, reqHeight, minLayerZ, maxLayerZ);
+            reqWidth, reqHeight, minLayerZ, maxLayerZ,
+            false);
 }
 
 ScreenshotClient::ScreenshotClient()
-    : mWidth(0), mHeight(0), mFormat(PIXEL_FORMAT_NONE) {
+    : mHaveBuffer(false) {
+    memset(&mBuffer, 0, sizeof(mBuffer));
 }
 
-status_t ScreenshotClient::update(const sp<IBinder>& display) {
-    sp<ISurfaceComposer> s(ComposerService::getComposerService());
-    if (s == NULL) return NO_INIT;
-    mHeap = 0;
-    return s->captureScreen(display, &mHeap,
-            &mWidth, &mHeight, &mFormat, 0, 0,
-            0, -1UL);
-}
-
-status_t ScreenshotClient::update(const sp<IBinder>& display,
-        uint32_t reqWidth, uint32_t reqHeight) {
-    sp<ISurfaceComposer> s(ComposerService::getComposerService());
-    if (s == NULL) return NO_INIT;
-    mHeap = 0;
-    return s->captureScreen(display, &mHeap,
-            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
-            0, -1UL);
+sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const {
+    if (mCpuConsumer == NULL) {
+        mCpuConsumer = new CpuConsumer(1);
+        mCpuConsumer->setName(String8("ScreenshotClient"));
+    }
+    return mCpuConsumer;
 }
 
 status_t ScreenshotClient::update(const sp<IBinder>& display,
@@ -648,38 +640,66 @@
         uint32_t minLayerZ, uint32_t maxLayerZ) {
     sp<ISurfaceComposer> s(ComposerService::getComposerService());
     if (s == NULL) return NO_INIT;
-    mHeap = 0;
-    return s->captureScreen(display, &mHeap,
-            &mWidth, &mHeight, &mFormat, reqWidth, reqHeight,
-            minLayerZ, maxLayerZ);
+    sp<CpuConsumer> cpuConsumer = getCpuConsumer();
+
+    if (mHaveBuffer) {
+        mCpuConsumer->unlockBuffer(mBuffer);
+        memset(&mBuffer, 0, sizeof(mBuffer));
+        mHaveBuffer = false;
+    }
+
+    status_t err = s->captureScreen(display,cpuConsumer->getBufferQueue(),
+            reqWidth, reqHeight, minLayerZ, maxLayerZ, true);
+
+    if (err == NO_ERROR) {
+        err = mCpuConsumer->lockNextBuffer(&mBuffer);
+        if (err == NO_ERROR) {
+            mHaveBuffer = true;
+        }
+    }
+    return err;
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display) {
+    return ScreenshotClient::update(display, 0, 0, 0, -1UL);
+}
+
+status_t ScreenshotClient::update(const sp<IBinder>& display,
+        uint32_t reqWidth, uint32_t reqHeight) {
+    return ScreenshotClient::update(display, reqWidth, reqHeight, 0, -1UL);
 }
 
 void ScreenshotClient::release() {
-    mHeap = 0;
+    if (mHaveBuffer) {
+        mCpuConsumer->unlockBuffer(mBuffer);
+        memset(&mBuffer, 0, sizeof(mBuffer));
+        mHaveBuffer = false;
+    }
+    mCpuConsumer.clear();
 }
 
 void const* ScreenshotClient::getPixels() const {
-    return mHeap->getBase();
+    return mBuffer.data;
 }
 
 uint32_t ScreenshotClient::getWidth() const {
-    return mWidth;
+    return mBuffer.width;
 }
 
 uint32_t ScreenshotClient::getHeight() const {
-    return mHeight;
+    return mBuffer.height;
 }
 
 PixelFormat ScreenshotClient::getFormat() const {
-    return mFormat;
+    return mBuffer.format;
 }
 
 uint32_t ScreenshotClient::getStride() const {
-    return mWidth;
+    return mBuffer.stride;
 }
 
 size_t ScreenshotClient::getSize() const {
-    return mHeap->getSize();
+    return mBuffer.stride * mBuffer.height * bytesPerPixel(mBuffer.format);
 }
 
 // ----------------------------------------------------------------------------