From 27e1a79bf7622f43803ca7e4635b1ac90b44b9bd Mon Sep 17 00:00:00 2001 From: Daniel Sandler Date: Tue, 27 Jul 2010 14:46:34 -0400 Subject: On-device screenshot support. This comes in the form of a command, `screenshot`, which will read /dev/graphics/fb0 (in a manner very similar to adb's framebuffer_service) and write to the specified PNG file. Additionally, dumpstate now accepts a -p flag (mnemonic: "picture" or "png") that, when specified, will cause a screenshot to be captured in the same directory as the bugreport. Future work: invoke `dumpstate -p` when the bugreport keychord is pressed, giving users a convenient way to attach screenshots to bug reports (or simply take screenshots at all without developer tools). Bug: 2216571 (and probably plenty of others) Change-Id: I36afbc55a0308a7bc01112ef39c4c62777efb203 --- cmds/screenshot/Android.mk | 16 ++++++ cmds/screenshot/screenshot.c | 118 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 cmds/screenshot/Android.mk create mode 100644 cmds/screenshot/screenshot.c (limited to 'cmds/screenshot') diff --git a/cmds/screenshot/Android.mk b/cmds/screenshot/Android.mk new file mode 100644 index 0000000..99c7aeb --- /dev/null +++ b/cmds/screenshot/Android.mk @@ -0,0 +1,16 @@ +ifneq ($(TARGET_SIMULATOR),true) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := screenshot.c + +LOCAL_MODULE := screenshot + +LOCAL_SHARED_LIBRARIES := libcutils libz +LOCAL_STATIC_LIBRARIES := libpng +LOCAL_C_INCLUDES += external/zlib + +include $(BUILD_EXECUTABLE) + +endif diff --git a/cmds/screenshot/screenshot.c b/cmds/screenshot/screenshot.c new file mode 100644 index 0000000..46e6507 --- /dev/null +++ b/cmds/screenshot/screenshot.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "private/android_filesystem_config.h" + +#define LOG_TAG "screenshot" +#include + +void take_screenshot(FILE *fb_in, FILE *fb_out) { + int fb; + char imgbuf[0x10000]; + struct fb_var_screeninfo vinfo; + png_structp png; + png_infop info; + unsigned int r,c,rowlen; + unsigned int bytespp,offset; + + fb = fileno(fb_in); + if(fb < 0) { + LOGE("failed to open framebuffer\n"); + return; + } + fb_in = fdopen(fb, "r"); + + if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) { + LOGE("failed to get framebuffer info\n"); + return; + } + fcntl(fb, F_SETFD, FD_CLOEXEC); + + png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png == NULL) { + LOGE("failed png_create_write_struct\n"); + fclose(fb_in); + return; + } + + png_init_io(png, fb_out); + info = png_create_info_struct(png); + if (info == NULL) { + LOGE("failed png_create_info_struct\n"); + png_destroy_write_struct(&png, NULL); + fclose(fb_in); + return; + } + if (setjmp(png_jmpbuf(png))) { + LOGE("failed png setjmp\n"); + png_destroy_write_struct(&png, NULL); + fclose(fb_in); + return; + } + + bytespp = vinfo.bits_per_pixel / 8; + png_set_IHDR(png, info, + vinfo.xres, vinfo.yres, vinfo.bits_per_pixel / 4, + PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + png_write_info(png, info); + + rowlen=vinfo.xres * bytespp; + if (rowlen > sizeof(imgbuf)) { + LOGE("crazy rowlen: %d\n", rowlen); + png_destroy_write_struct(&png, NULL); + fclose(fb_in); + return; + } + + offset = vinfo.xoffset * bytespp + vinfo.xres * vinfo.yoffset * bytespp; + fseek(fb_in, offset, SEEK_SET); + + for(r=0; r