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 36cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe// TODO: Fix Skia. 37cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic push 38cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic ignored "-Wunused-parameter" 39c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkImageEncoder.h> 40c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood#include <SkData.h> 41cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe#pragma GCC diagnostic pop 42c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 43c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodusing namespace android; 44c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 45c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic uint32_t DEFAULT_DISPLAY_ID = ISurfaceComposer::eDisplayIdMain; 46c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 47c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodstatic void usage(const char* pname) 48c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 49c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fprintf(stderr, 50c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "usage: %s [-hp] [-d display-id] [FILENAME]\n" 51c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -h: this message\n" 52c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -p: save the file as a png.\n" 53c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood " -d: specify the display id to capture, default %d.\n" 54c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "If FILENAME ends with .png it will be saved as a png.\n" 55c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood "If FILENAME is not given, the results will be printed to stdout.\n", 56c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood pname, DEFAULT_DISPLAY_ID 57c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ); 58c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 59c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 60b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reedstatic SkColorType flinger2skia(PixelFormat f) 61c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 62c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (f) { 63c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case PIXEL_FORMAT_RGB_565: 64b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed return kRGB_565_SkColorType; 65c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood default: 66b933055cf3f7f8ea89bfd3bc9c37a3891ff7310aMike Reed return kN32_SkColorType; 67c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 68c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 69c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 70cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khanstatic status_t notifyMediaScanner(const char* fileName) { 71cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan String8 cmd("am broadcast -a android.intent.action.MEDIA_SCANNER_SCAN_FILE -d file://"); 72cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan String8 fileUrl("\""); 73cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan fileUrl.append(fileName); 74cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan fileUrl.append("\""); 75cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan cmd.append(fileName); 76cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan cmd.append(" > /dev/null"); 77cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan int result = system(cmd.string()); 78cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan if (result < 0) { 79cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan fprintf(stderr, "Unable to broadcast intent for media scanner.\n"); 80cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan return UNKNOWN_ERROR; 81cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan } 82cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan return NO_ERROR; 83cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan} 84cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan 85c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwoodint main(int argc, char** argv) 86c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood{ 873b53fc5a84c4db40830d1810dee309accce66f09Martijn Coenen // setThreadPoolMaxThreadCount(0) actually tells the kernel it's 883b53fc5a84c4db40830d1810dee309accce66f09Martijn Coenen // not allowed to spawn any additional threads, but we still spawn 893b53fc5a84c4db40830d1810dee309accce66f09Martijn Coenen // a binder thread from userspace when we call startThreadPool(). 903b53fc5a84c4db40830d1810dee309accce66f09Martijn Coenen // See b/36066697 for rationale 913b53fc5a84c4db40830d1810dee309accce66f09Martijn Coenen ProcessState::self()->setThreadPoolMaxThreadCount(0); 920678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian ProcessState::self()->startThreadPool(); 930678a8c250832a5549703f533f6afea9d8729e43Mathias Agopian 94c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const char* pname = argv[0]; 95c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood bool png = false; 96c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int32_t displayId = DEFAULT_DISPLAY_ID; 97c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int c; 98c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood while ((c = getopt(argc, argv, "phd:")) != -1) { 99c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood switch (c) { 100c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'p': 101c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood png = true; 102c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 103c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'd': 104c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood displayId = atoi(optarg); 105c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood break; 106c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case '?': 107c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood case 'h': 108c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood usage(pname); 109c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 110c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 111c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 112c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood argc -= optind; 113c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood argv += optind; 114c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 115c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood int fd = -1; 116cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe const char* fn = NULL; 117c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (argc == 0) { 118c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fd = dup(STDOUT_FILENO); 119c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } else if (argc == 1) { 120cfed2326c7e77602fa6278ddf99203d9aaaf8df7Umair Khan fn = argv[0]; 121c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664); 122c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fd == -1) { 123c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno)); 124c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 125c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 126c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood const int len = strlen(fn); 127c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) { 128c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood png = true; 129c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 130c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 131bf89ae53c3d74365be4bf794283ca26f7d6d3fe1Prathmesh Prabhu 132c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (fd == -1) { 133c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood usage(pname); 134c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood return 1; 135c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 136c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 137c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood void const* mapbase = MAP_FAILED; 138c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ssize_t mapsize = -1; 139c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 140cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe void const* base = NULL; 1410137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian uint32_t w, s, h, f; 142c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size_t size = 0; 143c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 144cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza // Maps orientations from DisplayInfo to ISurfaceComposer 145cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza static const uint32_t ORIENTATION_MAP[] = { 146cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotateNone, // 0 == DISPLAY_ORIENTATION_0 147cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotate270, // 1 == DISPLAY_ORIENTATION_90 148cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotate180, // 2 == DISPLAY_ORIENTATION_180 149cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza ISurfaceComposer::eRotate90, // 3 == DISPLAY_ORIENTATION_270 150cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza }; 151cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza 152c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood ScreenshotClient screenshot; 153c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId); 154cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza if (display == NULL) { 155cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza fprintf(stderr, "Unable to get handle for display %d\n", displayId); 156cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza return 1; 157cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza } 158cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza 159cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza Vector<DisplayInfo> configs; 160cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza SurfaceComposerClient::getDisplayConfigs(display, &configs); 161cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza int activeConfig = SurfaceComposerClient::getActiveConfig(display); 162cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza if (static_cast<size_t>(activeConfig) >= configs.size()) { 163cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza fprintf(stderr, "Active config %d not inside configs (size %zu)\n", 164cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza activeConfig, configs.size()); 165cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza return 1; 166cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza } 167cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza uint8_t displayOrientation = configs[activeConfig].orientation; 168cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation]; 169cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza 170db7ecbe6994c5ec2cc46a6468300c927ebf7db37Robert Carr status_t result = screenshot.update(display, Rect(), 171db7ecbe6994c5ec2cc46a6468300c927ebf7db37Robert Carr 0 /* reqWidth */, 0 /* reqHeight */, 172db7ecbe6994c5ec2cc46a6468300c927ebf7db37Robert Carr INT32_MIN, INT32_MAX, /* all layers */ 173cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza false, captureOrientation); 174cf70d71781a40d197c3ecde89351976b27eb9a8aDan Stoza if (result == NO_ERROR) { 175c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood base = screenshot.getPixels(); 176c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood w = screenshot.getWidth(); 177c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood h = screenshot.getHeight(); 1780137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian s = screenshot.getStride(); 179c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood f = screenshot.getFormat(); 180c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood size = screenshot.getSize(); 181c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 182c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood 183cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (base != NULL) { 184c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (png) { 18510219fb261606fcc71c607167b28295b4578a10dHal Canary const SkImageInfo info = 18610219fb261606fcc71c607167b28295b4578a10dHal Canary SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType); 18710219fb261606fcc71c607167b28295b4578a10dHal Canary SkPixmap pixmap(info, base, s * bytesPerPixel(f)); 18810219fb261606fcc71c607167b28295b4578a10dHal Canary struct FDWStream final : public SkWStream { 18910219fb261606fcc71c607167b28295b4578a10dHal Canary size_t fBytesWritten = 0; 19010219fb261606fcc71c607167b28295b4578a10dHal Canary int fFd; 19110219fb261606fcc71c607167b28295b4578a10dHal Canary FDWStream(int f) : fFd(f) {} 19210219fb261606fcc71c607167b28295b4578a10dHal Canary size_t bytesWritten() const override { return fBytesWritten; } 19310219fb261606fcc71c607167b28295b4578a10dHal Canary bool write(const void* buffer, size_t size) override { 19410219fb261606fcc71c607167b28295b4578a10dHal Canary fBytesWritten += size; 19510219fb261606fcc71c607167b28295b4578a10dHal Canary return size == 0 || ::write(fFd, buffer, size) > 0; 19610219fb261606fcc71c607167b28295b4578a10dHal Canary } 19710219fb261606fcc71c607167b28295b4578a10dHal Canary } fdStream(fd); 19810219fb261606fcc71c607167b28295b4578a10dHal Canary (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100); 199cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe if (fn != NULL) { 200cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe notifyMediaScanner(fn); 201cfedceb8c180a2e176154d461659e0c3569dc931Andreas Gampe } 202c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } else { 203c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, &w, 4); 204c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, &h, 4); 205c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood write(fd, &f, 4); 2060137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian size_t Bpp = bytesPerPixel(f); 2070137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian for (size_t y=0 ; y<h ; y++) { 2080137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian write(fd, base, w*Bpp); 2090137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian base = (void *)((char *)base + s*Bpp); 2100137fb8937e69ed41cff3bf8cb0c1fea43daa3b5Mathias Agopian } 211c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 212c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 213c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood close(fd); 214c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood if (mapbase != MAP_FAILED) { 215c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood munmap((void *)mapbase, mapsize); 216c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood } 217909825886c58c7f9eeafb6223b6de91e29c97232Josh Gao 218909825886c58c7f9eeafb6223b6de91e29c97232Josh Gao // b/36066697: Avoid running static destructors. 2199377ce67a834c8c04fde555111fe44d0f728ed81Brian Carlstrom _exit(0); 220c59b2f9a774c024fe8c893d956cd2749a6bd2673Mike Lockwood} 221