From 689e091c7faa30f005b9adc0b7b3d2066c62be84 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 20 Nov 2017 18:33:05 -0800 Subject: [PATCH] Updated screenshot code to reflect native changes. The changes in native code removed using a GraphicBufferProducer and instead use only a GraphicBuffer to generate screenshots. Updated JNI code so it calls the screensot function that returns a GraphicBuffer and handle returning either a Surface, GraphicBuffer, or Bitmap. Also updated screencap shell code so it uses the new GraphicBuffer screenshot code. Test: Recents, screenshot from SystemUi, screenshot from shell. Change-Id: I6cb4f619e59461790a2a8f0cd2ea1192d9ae66b6 --- cmds/screencap/screencap.cpp | 97 ++++++++++++---------- core/java/android/view/SurfaceControl.java | 16 +--- core/jni/android_view_Surface.cpp | 18 +--- core/jni/android_view_SurfaceControl.cpp | 92 ++++++-------------- .../systemui/screenshot/GlobalScreenshot.java | 4 +- .../android/server/wm/TaskSnapshotController.java | 2 +- 6 files changed, 85 insertions(+), 144 deletions(-) diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index 6ded24648353..31722815276c 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -159,7 +159,7 @@ int main(int argc, char** argv) void const* mapbase = MAP_FAILED; ssize_t mapsize = -1; - void const* base = NULL; + void* base = NULL; uint32_t w, s, h, f; android_dataspace d; size_t size = 0; @@ -179,7 +179,6 @@ int main(int argc, char** argv) ProcessState::self()->setThreadPoolMaxThreadCount(0); ProcessState::self()->startThreadPool(); - ScreenshotClient screenshot; sp display = SurfaceComposerClient::getBuiltInDisplay(displayId); if (display == NULL) { fprintf(stderr, "Unable to get handle for display %d\n", displayId); @@ -199,51 +198,57 @@ int main(int argc, char** argv) uint8_t displayOrientation = configs[activeConfig].orientation; uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation]; - status_t result = screenshot.update(display, Rect(), - 0 /* reqWidth */, 0 /* reqHeight */, - INT32_MIN, INT32_MAX, /* all layers */ - false, captureOrientation); - if (result == NO_ERROR) { - base = screenshot.getPixels(); - w = screenshot.getWidth(); - h = screenshot.getHeight(); - s = screenshot.getStride(); - f = screenshot.getFormat(); - d = screenshot.getDataSpace(); - size = screenshot.getSize(); + sp outBuffer; + status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */, + 0 /* reqHeight */, INT32_MIN, INT32_MAX, /* all layers */ false, captureOrientation, + &outBuffer); + if (result != NO_ERROR) { + close(fd); + _exit(1); + } + + result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base); + + if (base == NULL) { + close(fd); + _exit(1); } - if (base != NULL) { - if (png) { - const SkImageInfo info = - SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, - dataSpaceToColorSpace(d)); - SkPixmap pixmap(info, base, s * bytesPerPixel(f)); - struct FDWStream final : public SkWStream { - size_t fBytesWritten = 0; - int fFd; - FDWStream(int f) : fFd(f) {} - size_t bytesWritten() const override { return fBytesWritten; } - bool write(const void* buffer, size_t size) override { - fBytesWritten += size; - return size == 0 || ::write(fFd, buffer, size) > 0; - } - } fdStream(fd); - (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100); - if (fn != NULL) { - notifyMediaScanner(fn); - } - } else { - uint32_t c = dataSpaceToInt(d); - write(fd, &w, 4); - write(fd, &h, 4); - write(fd, &f, 4); - write(fd, &c, 4); - size_t Bpp = bytesPerPixel(f); - for (size_t y=0 ; ygetWidth(); + h = outBuffer->getHeight(); + s = outBuffer->getStride(); + f = outBuffer->getPixelFormat(); + d = HAL_DATASPACE_UNKNOWN; + size = s * h * bytesPerPixel(f); + + if (png) { + const SkImageInfo info = + SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d)); + SkPixmap pixmap(info, base, s * bytesPerPixel(f)); + struct FDWStream final : public SkWStream { + size_t fBytesWritten = 0; + int fFd; + FDWStream(int f) : fFd(f) {} + size_t bytesWritten() const override { return fBytesWritten; } + bool write(const void* buffer, size_t size) override { + fBytesWritten += size; + return size == 0 || ::write(fFd, buffer, size) > 0; + } + } fdStream(fd); + (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100); + if (fn != NULL) { + notifyMediaScanner(fn); + } + } else { + uint32_t c = dataSpaceToInt(d); + write(fd, &w, 4); + write(fd, &h, 4); + write(fd, &f, 4); + write(fd, &c, 4); + size_t Bpp = bytesPerPixel(f); + for (size_t y=0 ; y(nativeObject); sp bp = graphicBufferForJavaObject(env, graphicBuffer); - if (bp == nullptr) { - return BAD_VALUE; - } - int err = ((ANativeWindow*)surface)->perform(surface, NATIVE_WINDOW_API_CONNECT, - NATIVE_WINDOW_API_CPU); - if (err != OK) { - return err; - } - err = surface->attachBuffer(bp->getNativeBuffer()); - if (err != OK) { - return err; - } - err = ((ANativeWindow*)surface)->queueBuffer(surface, bp->getNativeBuffer(), -1); - if (err != OK) { - return err; - } - err = surface->disconnect(NATIVE_WINDOW_API_CPU); + int err = Surface::attachAndQueueBuffer(surface, bp); return err; } diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index f77e6c4fa7b8..8c968a2a7083 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -167,7 +167,7 @@ static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz, maxLayer = INT32_MAX; } sp buffer; - status_t res = ScreenshotClient::captureToBuffer(displayToken, + status_t res = ScreenshotClient::capture(displayToken, sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform, rotation, &buffer); if (res != NO_ERROR) { @@ -201,15 +201,18 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, maxLayer = INT32_MAX; } - res = screenshot->update(displayToken, sourceCrop, width, height, - minLayer, maxLayer, useIdentityTransform, static_cast(rotation)); + sp buffer; + res = ScreenshotClient::capture(displayToken, sourceCrop, width, height, + minLayer, maxLayer, useIdentityTransform, static_cast(rotation), &buffer); if (res != NO_ERROR) { return NULL; } SkColorType colorType; SkAlphaType alphaType; - switch (screenshot->getFormat()) { + + PixelFormat format = buffer->getPixelFormat(); + switch (format) { case PIXEL_FORMAT_RGBX_8888: { colorType = kRGBA_8888_SkColorType; alphaType = kOpaque_SkAlphaType; @@ -235,66 +238,20 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz, } } - sk_sp colorSpace; - if (screenshot->getDataSpace() == HAL_DATASPACE_DISPLAY_P3) { - colorSpace = SkColorSpace::MakeRGB( - SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut); - } else { - colorSpace = SkColorSpace::MakeSRGB(); - } - - SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(), - screenshot->getHeight(), - colorType, - alphaType, - colorSpace); + SkImageInfo info = SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(), + colorType, alphaType, + SkColorSpace::MakeSRGB()); - const size_t rowBytes = - screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat()); - - if (!screenshotInfo.width() || !screenshotInfo.height()) { - return NULL; - } - - auto bitmap = new Bitmap( - (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot, - screenshotInfo, rowBytes); - screenshot.release(); - bitmap->setImmutable(); - return bitmap::createBitmap(env, bitmap, - android::bitmap::kBitmapCreateFlag_Premultiplied, NULL); + auto bitmap = sk_sp(new Bitmap(buffer.get(), info)); + return bitmap::createBitmap(env, bitmap.release(), + android::bitmap::kBitmapCreateFlag_Premultiplied, NULL); } static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj, jobject surfaceObj, jobject sourceCropObj, jint width, jint height, jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) { sp displayToken = ibinderForJavaObject(env, displayTokenObj); - if (displayToken != NULL) { - sp consumer = android_view_Surface_getSurface(env, surfaceObj); - if (consumer != NULL) { - int left = env->GetIntField(sourceCropObj, gRectClassInfo.left); - int top = env->GetIntField(sourceCropObj, gRectClassInfo.top); - int right = env->GetIntField(sourceCropObj, gRectClassInfo.right); - int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom); - Rect sourceCrop(left, top, right, bottom); - - if (allLayers) { - minLayer = INT32_MIN; - maxLayer = INT32_MAX; - } - ScreenshotClient::capture(displayToken, - consumer->getIGraphicBufferProducer(), sourceCrop, - width, height, minLayer, maxLayer, - useIdentityTransform); - } - } -} - -static void nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken, - jobject surfaceObj, jobject sourceCropObj, jfloat frameScale) { - - sp layerHandle = ibinderForJavaObject(env, layerHandleToken); - if (layerHandle == NULL) { + if (displayToken == NULL) { return; } @@ -308,11 +265,19 @@ static void nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleTo sourceCrop = rectFromObj(env, sourceCropObj); } - ScreenshotClient::captureLayers(layerHandle, consumer->getIGraphicBufferProducer(), sourceCrop, - frameScale); + if (allLayers) { + minLayer = INT32_MIN; + maxLayer = INT32_MAX; + } + + sp buffer; + ScreenshotClient::capture(displayToken, sourceCrop, width, height, minLayer, maxLayer, + useIdentityTransform, 0, &buffer); + + Surface::attachAndQueueBuffer(consumer.get(), buffer); } -static jobject nativeCaptureLayersToBuffer(JNIEnv* env, jclass clazz, jobject layerHandleToken, +static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken, jobject sourceCropObj, jfloat frameScale) { sp layerHandle = ibinderForJavaObject(env, layerHandleToken); @@ -326,8 +291,7 @@ static jobject nativeCaptureLayersToBuffer(JNIEnv* env, jclass clazz, jobject la } sp buffer; - status_t res = ScreenshotClient::captureLayersToBuffer(layerHandle, sourceCrop, frameScale, - &buffer); + status_t res = ScreenshotClient::captureLayers(layerHandle, sourceCrop, frameScale, &buffer); if (res != NO_ERROR) { return NULL; } @@ -1010,10 +974,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { {"nativeScreenshotToBuffer", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;", (void*)nativeScreenshotToBuffer }, - {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;F)V", - (void*)nativeCaptureLayers }, {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;", - (void*)nativeCaptureLayersToBuffer }, + (void*)nativeCaptureLayers }, }; int register_android_view_SurfaceControl(JNIEnv* env) diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java index 991c3c83cbc1..e9096447bbf6 100644 --- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java +++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java @@ -162,7 +162,7 @@ class SaveImageInBackgroundTask extends AsyncTask { Matrix matrix = new Matrix(); int overlayColor = 0x40FFFFFF; - Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, data.image.getConfig()); + Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888); matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2); c.setBitmap(picture); c.drawBitmap(data.image, matrix, paint); @@ -171,7 +171,7 @@ class SaveImageInBackgroundTask extends AsyncTask { // Note, we can't use the preview for the small icon, since it is non-square float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight); - Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, data.image.getConfig()); + Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888); matrix.setScale(scale, scale); matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2, (iconSize - (scale * mImageHeight)) / 2); diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java index 84e475a25187..43a089373a35 100644 --- a/services/core/java/com/android/server/wm/TaskSnapshotController.java +++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java @@ -226,7 +226,7 @@ class TaskSnapshotController { final Rect taskFrame = new Rect(); task.getBounds(taskFrame); - final GraphicBuffer buffer = SurfaceControl.captureLayersToBuffer( + final GraphicBuffer buffer = SurfaceControl.captureLayers( task.getSurfaceControl().getHandle(), taskFrame, scaleFraction); if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) { -- 2.11.0