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.os.Binder; 24 import android.os.RemoteException; 25 import android.util.Log; 26 import android.view.Display; 27 import android.view.Surface; 28 import android.view.SurfaceControl; 29 30 /** 31 * Helper class used to take screenshots. 32 * 33 * TODO: logic below was copied and pasted from UiAutomation; it should be refactored into a common 34 * component that could be used by both (Shell and UiAutomation). 35 */ 36 final class Screenshooter { 37 38 private static final String TAG = "Screenshooter"; 39 40 /** Rotation constant: Freeze rotation to 0 degrees (natural orientation) */ 41 public static final int ROTATION_FREEZE_0 = Surface.ROTATION_0; 42 43 /** Rotation constant: Freeze rotation to 90 degrees . */ 44 public static final int ROTATION_FREEZE_90 = Surface.ROTATION_90; 45 46 /** Rotation constant: Freeze rotation to 180 degrees . */ 47 public static final int ROTATION_FREEZE_180 = Surface.ROTATION_180; 48 49 /** Rotation constant: Freeze rotation to 270 degrees . */ 50 public static final int ROTATION_FREEZE_270 = Surface.ROTATION_270; 51 52 /** 53 * Takes a screenshot. 54 * 55 * @return The screenshot bitmap on success, null otherwise. 56 */ 57 static Bitmap takeScreenshot() { 58 Display display = DisplayManagerGlobal.getInstance() 59 .getRealDisplay(Display.DEFAULT_DISPLAY); 60 Point displaySize = new Point(); 61 display.getRealSize(displaySize); 62 final int displayWidth = displaySize.x; 63 final int displayHeight = displaySize.y; 64 65 final float screenshotWidth; 66 final float screenshotHeight; 67 68 final int rotation = display.getRotation(); 69 switch (rotation) { 70 case ROTATION_FREEZE_0: { 71 screenshotWidth = displayWidth; 72 screenshotHeight = displayHeight; 73 } break; 74 case ROTATION_FREEZE_90: { 75 screenshotWidth = displayHeight; 76 screenshotHeight = displayWidth; 77 } break; 78 case ROTATION_FREEZE_180: { 79 screenshotWidth = displayWidth; 80 screenshotHeight = displayHeight; 81 } break; 82 case ROTATION_FREEZE_270: { 83 screenshotWidth = displayHeight; 84 screenshotHeight = displayWidth; 85 } break; 86 default: { 87 throw new IllegalArgumentException("Invalid rotation: " 88 + rotation); 89 } 90 } 91 92 Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight); 93 // Take the screenshot 94 Bitmap screenShot = 95 SurfaceControl.screenshot((int) screenshotWidth, (int) screenshotHeight); 96 if (screenShot == null) { 97 Log.e(TAG, "Failed to take screenshot of dimensions " + screenshotWidth + " x " 98 + screenshotHeight); 99 return null; 100 } 101 102 // Rotate the screenshot to the current orientation 103 if (rotation != ROTATION_FREEZE_0) { 104 Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight, 105 Bitmap.Config.ARGB_8888); 106 Canvas canvas = new Canvas(unrotatedScreenShot); 107 canvas.translate(unrotatedScreenShot.getWidth() / 2, 108 unrotatedScreenShot.getHeight() / 2); 109 canvas.rotate(getDegreesForRotation(rotation)); 110 canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2); 111 canvas.drawBitmap(screenShot, 0, 0, null); 112 canvas.setBitmap(null); 113 screenShot.recycle(); 114 screenShot = unrotatedScreenShot; 115 } 116 117 // Optimization 118 screenShot.setHasAlpha(false); 119 120 return screenShot; 121 } 122 123 private static float getDegreesForRotation(int value) { 124 switch (value) { 125 case Surface.ROTATION_90: { 126 return 360f - 90f; 127 } 128 case Surface.ROTATION_180: { 129 return 360f - 180f; 130 } 131 case Surface.ROTATION_270: { 132 return 360f - 270f; 133 } default: { 134 return 0; 135 } 136 } 137 } 138 139 } 140