From c59b2f9a774c024fe8c893d956cd2749a6bd2673 Mon Sep 17 00:00:00 2001 From: Mike Lockwood Date: Wed, 24 Oct 2012 12:31:10 -0700 Subject: More changes to fix PDK build: move screencap back to frameworks/base move libdiskusage to frameworks/native Change-Id: I8abe425c4bbf305bbe8650094c40c16df8c6d5e4 --- cmds/screencap/Android.mk | 26 ++++++ cmds/screencap/screencap.cpp | 195 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 cmds/screencap/Android.mk create mode 100644 cmds/screencap/screencap.cpp (limited to 'cmds/screencap') diff --git a/cmds/screencap/Android.mk b/cmds/screencap/Android.mk new file mode 100644 index 0000000..ca8008b --- /dev/null +++ b/cmds/screencap/Android.mk @@ -0,0 +1,26 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + screencap.cpp + +LOCAL_SHARED_LIBRARIES := \ + libcutils \ + libutils \ + libbinder \ + libskia \ + libui \ + libgui + +LOCAL_MODULE:= screencap + +LOCAL_MODULE_TAGS := optional + +LOCAL_C_INCLUDES += \ + external/skia/include/core \ + external/skia/include/effects \ + external/skia/include/images \ + external/skia/src/ports \ + external/skia/include/utils + +include $(BUILD_EXECUTABLE) diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp new file mode 100644 index 0000000..a1ea81a --- /dev/null +++ b/cmds/screencap/screencap.cpp @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +using namespace android; + +static uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain; + +static void usage(const char* pname) +{ + fprintf(stderr, + "usage: %s [-hp] [-d display-id] [FILENAME]\n" + " -h: this message\n" + " -p: save the file as a png.\n" + " -d: specify the display id to capture, default %d.\n" + "If FILENAME ends with .png it will be saved as a png.\n" + "If FILENAME is not given, the results will be printed to stdout.\n", + pname, DEFAULT_DISPLAY_ID + ); +} + +static SkBitmap::Config flinger2skia(PixelFormat f) +{ + switch (f) { + case PIXEL_FORMAT_A_8: + return SkBitmap::kA8_Config; + case PIXEL_FORMAT_RGB_565: + return SkBitmap::kRGB_565_Config; + case PIXEL_FORMAT_RGBA_4444: + return SkBitmap::kARGB_4444_Config; + default: + return SkBitmap::kARGB_8888_Config; + } +} + +static status_t vinfoToPixelFormat(const fb_var_screeninfo& vinfo, + uint32_t* bytespp, uint32_t* f) +{ + + switch (vinfo.bits_per_pixel) { + case 16: + *f = PIXEL_FORMAT_RGB_565; + *bytespp = 2; + break; + case 24: + *f = PIXEL_FORMAT_RGB_888; + *bytespp = 3; + break; + case 32: + // TODO: do better decoding of vinfo here + *f = PIXEL_FORMAT_RGBX_8888; + *bytespp = 4; + break; + default: + return BAD_VALUE; + } + return NO_ERROR; +} + +int main(int argc, char** argv) +{ + const char* pname = argv[0]; + bool png = false; + int32_t displayId = DEFAULT_DISPLAY_ID; + int c; + while ((c = getopt(argc, argv, "phd:")) != -1) { + switch (c) { + case 'p': + png = true; + break; + case 'd': + displayId = atoi(optarg); + break; + case '?': + case 'h': + usage(pname); + return 1; + } + } + argc -= optind; + argv += optind; + + int fd = -1; + if (argc == 0) { + fd = dup(STDOUT_FILENO); + } else if (argc == 1) { + const char* fn = argv[0]; + fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); + if (fd == -1) { + fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno)); + return 1; + } + const int len = strlen(fn); + if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) { + png = true; + } + } + + if (fd == -1) { + usage(pname); + return 1; + } + + void const* mapbase = MAP_FAILED; + ssize_t mapsize = -1; + + void const* base = 0; + uint32_t w, h, f; + size_t size = 0; + + ScreenshotClient screenshot; + sp display = SurfaceComposerClient::getBuiltInDisplay(displayId); + if (display != NULL && screenshot.update(display) == NO_ERROR) { + base = screenshot.getPixels(); + w = screenshot.getWidth(); + h = screenshot.getHeight(); + f = screenshot.getFormat(); + size = screenshot.getSize(); + } else { + const char* fbpath = "/dev/graphics/fb0"; + int fb = open(fbpath, O_RDONLY); + if (fb >= 0) { + struct fb_var_screeninfo vinfo; + if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) { + uint32_t bytespp; + if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) { + size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp; + w = vinfo.xres; + h = vinfo.yres; + size = w*h*bytespp; + mapsize = offset + size; + mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0); + if (mapbase != MAP_FAILED) { + base = (void const *)((char const *)mapbase + offset); + } + } + } + close(fb); + } + } + + if (base) { + if (png) { + SkBitmap b; + b.setConfig(flinger2skia(f), w, h); + b.setPixels((void*)base); + SkDynamicMemoryWStream stream; + SkImageEncoder::EncodeStream(&stream, b, + SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality); + SkData* streamData = stream.copyToData(); + write(fd, streamData->data(), streamData->size()); + streamData->unref(); + } else { + write(fd, &w, 4); + write(fd, &h, 4); + write(fd, &f, 4); + write(fd, base, size); + } + } + close(fd); + if (mapbase != MAP_FAILED) { + munmap((void *)mapbase, mapsize); + } + return 0; +} -- cgit v1.1