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}