1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.shell; 18 19 import android.graphics.Bitmap; 20 import android.graphics.Canvas; 21 import android.graphics.Point; 22 import android.hardware.display.DisplayManagerGlobal; 23 import android.util.Log; 24 import android.view.Display; 25 import android.view.Surface; 26 import android.view.SurfaceControl; 27 28 /** 29 * Helper class used to take screenshots. 30 * 31 * TODO: logic below was copied and pasted from UiAutomation; it should be refactored into a common 32 * component that could be used by both (Shell and UiAutomation). 33 */ 34 final class Screenshooter { 35 36 private static final String TAG = "Screenshooter"; 37 38 /** Rotation constant: Freeze rotation to 0 degrees (natural orientation) */ 39 public static final int ROTATION_FREEZE_0 = Surface.ROTATION_0; 40 41 /** Rotation constant: Freeze rotation to 90 degrees . */ 42 public static final int ROTATION_FREEZE_90 = Surface.ROTATION_90; 43 44 /** Rotation constant: Freeze rotation to 180 degrees . */ 45 public static final int ROTATION_FREEZE_180 = Surface.ROTATION_180; 46 47 /** Rotation constant: Freeze rotation to 270 degrees . */ 48 public static final int ROTATION_FREEZE_270 = Surface.ROTATION_270; 49 50 /** 51 * Takes a screenshot. 52 * 53 * @return The screenshot bitmap on success, null otherwise. 54 */ takeScreenshot()55 static Bitmap takeScreenshot() { 56 Display display = DisplayManagerGlobal.getInstance() 57 .getRealDisplay(Display.DEFAULT_DISPLAY); 58 Point displaySize = new Point(); 59 display.getRealSize(displaySize); 60 final int displayWidth = displaySize.x; 61 final int displayHeight = displaySize.y; 62 63 final float screenshotWidth; 64 final float screenshotHeight; 65 66 final int rotation = display.getRotation(); 67 switch (rotation) { 68 case ROTATION_FREEZE_0: { 69 screenshotWidth = displayWidth; 70 screenshotHeight = displayHeight; 71 } break; 72 case ROTATION_FREEZE_90: { 73 screenshotWidth = displayHeight; 74 screenshotHeight = displayWidth; 75 } break; 76 case ROTATION_FREEZE_180: { 77 screenshotWidth = displayWidth; 78 screenshotHeight = displayHeight; 79 } break; 80 case ROTATION_FREEZE_270: { 81 screenshotWidth = displayHeight; 82 screenshotHeight = displayWidth; 83 } break; 84 default: { 85 throw new IllegalArgumentException("Invalid rotation: " 86 + rotation); 87 } 88 } 89 90 Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight); 91 // Take the screenshot 92 Bitmap screenShot = 93 SurfaceControl.screenshot((int) screenshotWidth, (int) screenshotHeight); 94 if (screenShot == null) { 95 Log.e(TAG, "Failed to take screenshot of dimensions " + screenshotWidth + " x " 96 + screenshotHeight); 97 return null; 98 } 99 100 // Rotate the screenshot to the current orientation 101 if (rotation != ROTATION_FREEZE_0) { 102 Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight, 103 Bitmap.Config.ARGB_8888, screenShot.hasAlpha(), screenShot.getColorSpace()); 104 Canvas canvas = new Canvas(unrotatedScreenShot); 105 canvas.translate(unrotatedScreenShot.getWidth() / 2, 106 unrotatedScreenShot.getHeight() / 2); 107 canvas.rotate(getDegreesForRotation(rotation)); 108 canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2); 109 canvas.drawBitmap(screenShot, 0, 0, null); 110 canvas.setBitmap(null); 111 screenShot.recycle(); 112 screenShot = unrotatedScreenShot; 113 } 114 115 // Optimization 116 screenShot.setHasAlpha(false); 117 118 return screenShot; 119 } 120 getDegreesForRotation(int value)121 private static float getDegreesForRotation(int value) { 122 switch (value) { 123 case Surface.ROTATION_90: { 124 return 360f - 90f; 125 } 126 case Surface.ROTATION_180: { 127 return 360f - 180f; 128 } 129 case Surface.ROTATION_270: { 130 return 360f - 270f; 131 } default: { 132 return 0; 133 } 134 } 135 } 136 137 } 138