1c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood/* 2c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * Copyright (C) 2010 The Android Open Source Project 3c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * 4c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * Licensed under the Apache License, Version 2.0 (the "License"); 5c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * you may not use this file except in compliance with the License. 6c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * You may obtain a copy of the License at 7c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * 8c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * http://www.apache.org/licenses/LICENSE-2.0 9c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * 10c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * Unless required by applicable law or agreed to in writing, software 11c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * distributed under the License is distributed on an "AS IS" BASIS, 12c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * See the License for the specific language governing permissions and 14c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood * limitations under the License. 15c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood */ 16c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 17c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <errno.h> 18c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <unistd.h> 19c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <stdio.h> 20c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <fcntl.h> 21cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan#include <stdlib.h> 22cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan#include <string.h> 23c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 24c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <linux/fb.h> 25c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <sys/ioctl.h> 26c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <sys/mman.h> 27c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 280678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian#include <binder/ProcessState.h> 290678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian 30c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <gui/SurfaceComposerClient.h> 31c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <gui/ISurfaceComposer.h> 32c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 33cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza#include <ui/DisplayInfo.h> 340137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian#include <ui/PixelFormat.h> 350137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian 3626a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy#include <system/graphics.h> 3726a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy 38cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe// TODO: Fix Skia. 39cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic push 40cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter" 41c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkImageEncoder.h> 42c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkData.h> 4326a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy#include <SkColorSpace.h> 44cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic pop 45c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 46c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodusing namespace android; 47c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 48c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain; 49c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 5026a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy#define COLORSPACE_UNKNOWN 0 5126a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy#define COLORSPACE_SRGB 1 5226a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy#define COLORSPACE_DISPLAY_P3 2 5326a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy 54c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic void usage(const char* pname) 55c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 56c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fprintf(stderr, 57c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "usage: %s [-hp] [-d display-id] [FILENAME]\n" 58c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -h: this message\n" 59c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -p: save the file as a png.\n" 60c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -d: specify the display id to capture, default %d.\n" 61c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "If FILENAME ends with .png it will be saved as a png.\n" 62c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "If FILENAME is not given, the results will be printed to stdout.\n", 63c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood pname, DEFAULT_DISPLAY_ID 64c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ); 65c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 66c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 67b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reedstatic SkColorType flinger2skia(PixelFormat f) 68c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 69c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (f) { 70c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case PIXEL_FORMAT_RGB_565: 71b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed return kRGB_565_SkColorType; 72c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood default: 73b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed return kN32_SkColorType; 74c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 75c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 76c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 7726a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guystatic sk_sp<SkColorSpace> dataSpaceToColorSpace(android_dataspace d) 7826a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy{ 7926a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy switch (d) { 8026a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy case HAL_DATASPACE_V0_SRGB: 8126a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy return SkColorSpace::MakeSRGB(); 8226a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy case HAL_DATASPACE_DISPLAY_P3: 8326a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy return SkColorSpace::MakeRGB( 8426a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut); 8526a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy default: 8626a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy return nullptr; 8726a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy } 8826a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy} 8926a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy 9026a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guystatic uint32_t dataSpaceToInt(android_dataspace d) 9126a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy{ 9226a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy switch (d) { 9326a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy case HAL_DATASPACE_V0_SRGB: 9426a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy return COLORSPACE_SRGB; 9526a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy case HAL_DATASPACE_DISPLAY_P3: 9626a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy return COLORSPACE_DISPLAY_P3; 9726a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy default: 9826a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy return COLORSPACE_UNKNOWN; 9926a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy } 10026a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy} 10126a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy 102cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khanstatic status_t notifyMediaScanner(const char* fileName) { 103cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://"); 104cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan cmd.append(fileName); 105cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan cmd.append(" > /dev/null"); 106cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan int result = system(cmd.string()); 107cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan if (result < 0) { 108cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan fprintf(stderr, "Unable to broadcast intent for media scanner.\n"); 109cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan return UNKNOWN_ERROR; 110cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan } 111cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan return NO_ERROR; 112cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan} 113cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan 114c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodint main(int argc, char** argv) 115c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 116c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const char* pname = argv[0]; 117c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood bool png = false; 118c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int32_t displayId = DEFAULT_DISPLAY_ID; 119c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int c; 120c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood while ((c = getopt(argc, argv, "phd:")) != -1) { 121c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (c) { 122c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'p': 123c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood png = true; 124c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 125c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'd': 126c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood displayId = atoi(optarg); 127c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 128c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case '?': 129c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'h': 130c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood usage(pname); 131c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 132c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 133c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 134c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood argc -= optind; 135c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood argv += optind; 136c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 137c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int fd = -1; 138cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe const char* fn = NULL; 139c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (argc == 0) { 140c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fd = dup(STDOUT_FILENO); 141c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } else if (argc == 1) { 142cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan fn = argv[0]; 143c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); 144c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fd == -1) { 145c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno)); 146c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 147c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 148c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const int len = strlen(fn); 149c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) { 150c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood png = true; 151c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 152c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 153bf89ae53c3d74365be4bf794283ca26f7d6d3fe1Prathmesh Prabhu 154c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fd == -1) { 155c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood usage(pname); 156c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 157c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 158c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 159c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood void const* mapbase = MAP_FAILED; 160c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ssize_t mapsize = -1; 161c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 162d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten void* base = NULL; 1630137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian uint32_t w, s, h, f; 16426a2b97dbe48ee45e9ae70110714048f2f360f97Romain Guy android_dataspace d; 165c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size_t size = 0; 166c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 167cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza // Maps orientations from DisplayInfo to ISurfaceComposer 168cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza static const uint32_t ORIENTATION_MAP[] = { 169cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotateNone, // 0 == DISPLAY_ORIENTATION_0 170cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotate270, // 1 == DISPLAY_ORIENTATION_90 171cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotate180, // 2 == DISPLAY_ORIENTATION_180 172cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotate90, // 3 == DISPLAY_ORIENTATION_270 173cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza }; 174cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza 17548b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen // setThreadPoolMaxThreadCount(0) actually tells the kernel it's 17648b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen // not allowed to spawn any additional threads, but we still spawn 17748b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen // a binder thread from userspace when we call startThreadPool(). 17848b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen // See b/36066697 for rationale 17948b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen ProcessState::self()->setThreadPoolMaxThreadCount(0); 18048b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen ProcessState::self()->startThreadPool(); 18148b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen 182c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId); 183cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza if (display == NULL) { 184cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza fprintf(stderr, "Unable to get handle for display %d\n", displayId); 18548b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen // b/36066697: Avoid running static destructors. 18648b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen _exit(1); 187cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza } 188cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza 189cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza Vector<DisplayInfo> configs; 190cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza SurfaceComposerClient::getDisplayConfigs(display, &configs); 191cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza int activeConfig = SurfaceComposerClient::getActiveConfig(display); 192cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza if (static_cast<size_t>(activeConfig) >= configs.size()) { 193cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza fprintf(stderr, "Active config %d not inside configs (size %zu)\n", 194cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza activeConfig, configs.size()); 19548b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen // b/36066697: Avoid running static destructors. 19648b7408201bd4614b75a4713e5104b9eee9a1cbeMartijn Coenen _exit(1); 197cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza } 198cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza uint8_t displayOrientation = configs[activeConfig].orientation; 199cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation]; 200cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza 201d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten sp<GraphicBuffer> outBuffer; 202d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */, 203d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten 0 /* reqHeight */, INT32_MIN, INT32_MAX, /* all layers */ false, captureOrientation, 204d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten &outBuffer); 205d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten if (result != NO_ERROR) { 206d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten close(fd); 207d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten _exit(1); 208d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten } 209d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten 210d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base); 211d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten 212d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten if (base == NULL) { 213d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten close(fd); 214d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten _exit(1); 215c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 216c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 217d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten w = outBuffer->getWidth(); 218d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten h = outBuffer->getHeight(); 219d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten s = outBuffer->getStride(); 220d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten f = outBuffer->getPixelFormat(); 221d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten d = HAL_DATASPACE_UNKNOWN; 222d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten size = s * h * bytesPerPixel(f); 223d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten 224d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten if (png) { 225d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten const SkImageInfo info = 226d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d)); 227d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten SkPixmap pixmap(info, base, s * bytesPerPixel(f)); 228d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten struct FDWStream final : public SkWStream { 229d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten size_t fBytesWritten = 0; 230d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten int fFd; 231d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten FDWStream(int f) : fFd(f) {} 232d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten size_t bytesWritten() const override { return fBytesWritten; } 233d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten bool write(const void* buffer, size_t size) override { 234d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten fBytesWritten += size; 235d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten return size == 0 || ::write(fFd, buffer, size) > 0; 236d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten } 237d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten } fdStream(fd); 238d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100); 239d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten if (fn != NULL) { 240d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten notifyMediaScanner(fn); 241d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten } 242d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten } else { 243d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten uint32_t c = dataSpaceToInt(d); 244d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten write(fd, &w, 4); 245d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten write(fd, &h, 4); 246d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten write(fd, &f, 4); 247d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten write(fd, &c, 4); 248d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten size_t Bpp = bytesPerPixel(f); 249d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten for (size_t y=0 ; y<h ; y++) { 250d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten write(fd, base, w*Bpp); 251d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten base = (void *)((char *)base + s*Bpp); 252c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 253c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 254c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood close(fd); 255c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (mapbase != MAP_FAILED) { 256c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood munmap((void *)mapbase, mapsize); 257c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 258909825886c58c7f9eeafb6223b6de91e29c97232Josh Gao 259909825886c58c7f9eeafb6223b6de91e29c97232Josh Gao // b/36066697: Avoid running static destructors. 2609377ce67a834c8c04fde555111fe44d0f728ed81Brian Carlstrom _exit(0); 261d7ec64ccd0c2b180fc9fd3ff526642e5e7e28af0Chavi Weingarten}