From a3ef09430f254204274b667a8dfba654ef0c8396 Mon Sep 17 00:00:00 2001 From: Derek Sollenberger Date: Wed, 8 Apr 2020 15:47:55 -0400 Subject: [PATCH] Use public APIs for decoding images for screencap HWUI is restricting access to only a set of stable C APIs. Callers like boot animation are being converted to either the stable C or NDK APIs. Test: build and verify screencap cmd line for launcher Bug: 150782769 Change-Id: I87e1752409ccfeef22a082c389902b0883ad2bee --- cmds/screencap/Android.bp | 2 +- cmds/screencap/screencap.cpp | 75 ++++++++++++++---------------------- 2 files changed, 30 insertions(+), 47 deletions(-) diff --git a/cmds/screencap/Android.bp b/cmds/screencap/Android.bp index 248c675896962..fc628a696afaf 100644 --- a/cmds/screencap/Android.bp +++ b/cmds/screencap/Android.bp @@ -7,7 +7,7 @@ cc_binary { "libcutils", "libutils", "libbinder", - "libhwui", + "libjnigraphics", "libui", "libgui", ], diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp index 4410f1c4570c0..e67b78ee1b2d3 100644 --- a/cmds/screencap/screencap.cpp +++ b/cmds/screencap/screencap.cpp @@ -26,6 +26,8 @@ #include #include +#include + #include #include @@ -37,14 +39,6 @@ #include -// TODO: Fix Skia. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-parameter" -#include -#include -#include -#pragma GCC diagnostic pop - using namespace android; #define COLORSPACE_UNKNOWN 0 @@ -65,25 +59,13 @@ static void usage(const char* pname, PhysicalDisplayId displayId) pname, displayId); } -static SkColorType flinger2skia(PixelFormat f) +static int32_t flinger2bitmapFormat(PixelFormat f) { switch (f) { case PIXEL_FORMAT_RGB_565: - return kRGB_565_SkColorType; + return ANDROID_BITMAP_FORMAT_RGB_565; default: - return kN32_SkColorType; - } -} - -static sk_sp dataSpaceToColorSpace(ui::Dataspace d) -{ - switch (d) { - case ui::Dataspace::V0_SRGB: - return SkColorSpace::MakeSRGB(); - case ui::Dataspace::DISPLAY_P3: - return SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB, SkNamedGamut::kDCIP3); - default: - return nullptr; + return ANDROID_BITMAP_FORMAT_RGBA_8888; } } @@ -192,8 +174,6 @@ int main(int argc, char** argv) ssize_t mapsize = -1; void* base = NULL; - uint32_t w, s, h, f; - size_t size = 0; // setThreadPoolMaxThreadCount(0) actually tells the kernel it's // not allowed to spawn any additional threads, but we still spawn @@ -225,33 +205,36 @@ int main(int argc, char** argv) return 1; } - w = outBuffer->getWidth(); - h = outBuffer->getHeight(); - s = outBuffer->getStride(); - f = outBuffer->getPixelFormat(); - size = s * h * bytesPerPixel(f); - if (png) { - const SkImageInfo info = - SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, - dataSpaceToColorSpace(outDataspace)); - 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); + AndroidBitmapInfo info; + info.format = flinger2bitmapFormat(outBuffer->getPixelFormat()); + info.flags = ANDROID_BITMAP_FLAGS_ALPHA_PREMUL; + info.width = outBuffer->getWidth(); + info.height = outBuffer->getHeight(); + info.stride = outBuffer->getStride() * bytesPerPixel(outBuffer->getPixelFormat()); + + int result = AndroidBitmap_compress(&info, static_cast(outDataspace), base, + ANDROID_BITMAP_COMPRESS_FORMAT_PNG, 100, &fd, + [](void* fdPtr, const void* data, size_t size) -> bool { + int bytesWritten = write(*static_cast(fdPtr), + data, size); + return bytesWritten == size; + }); + + if (result != ANDROID_BITMAP_RESULT_SUCCESS) { + fprintf(stderr, "Failed to compress PNG (error code: %d)\n", result); + } + if (fn != NULL) { notifyMediaScanner(fn); } } else { + uint32_t w = outBuffer->getWidth(); + uint32_t h = outBuffer->getHeight(); + uint32_t s = outBuffer->getStride(); + uint32_t f = outBuffer->getPixelFormat(); uint32_t c = dataSpaceToInt(outDataspace); + write(fd, &w, 4); write(fd, &h, 4); write(fd, &f, 4);