Merge changes from topic "hw_bitmap"
* changes:
Update screenshot requests to render proper crop and rotation.
Revert "Revert "Updated screenshot code to reflect native changes.""
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 6ded246..3172281 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -159,7 +159,7 @@
void const* mapbase = MAP_FAILED;
ssize_t mapsize = -1;
- void const* base = NULL;
+ void* base = NULL;
uint32_t w, s, h, f;
android_dataspace d;
size_t size = 0;
@@ -179,7 +179,6 @@
ProcessState::self()->setThreadPoolMaxThreadCount(0);
ProcessState::self()->startThreadPool();
- ScreenshotClient screenshot;
sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
if (display == NULL) {
fprintf(stderr, "Unable to get handle for display %d\n", displayId);
@@ -199,51 +198,57 @@
uint8_t displayOrientation = configs[activeConfig].orientation;
uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
- status_t result = screenshot.update(display, Rect(),
- 0 /* reqWidth */, 0 /* reqHeight */,
- INT32_MIN, INT32_MAX, /* all layers */
- false, captureOrientation);
- if (result == NO_ERROR) {
- base = screenshot.getPixels();
- w = screenshot.getWidth();
- h = screenshot.getHeight();
- s = screenshot.getStride();
- f = screenshot.getFormat();
- d = screenshot.getDataSpace();
- size = screenshot.getSize();
+ sp<GraphicBuffer> outBuffer;
+ status_t result = ScreenshotClient::capture(display, Rect(), 0 /* reqWidth */,
+ 0 /* reqHeight */, INT32_MIN, INT32_MAX, /* all layers */ false, captureOrientation,
+ &outBuffer);
+ if (result != NO_ERROR) {
+ close(fd);
+ _exit(1);
}
- if (base != NULL) {
- if (png) {
- const SkImageInfo info =
- SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType,
- dataSpaceToColorSpace(d));
- SkPixmap pixmap(info, base, s * bytesPerPixel(f));
- struct FDWStream final : public SkWStream {
- size_t fBytesWritten = 0;
- int fFd;
- FDWStream(int f) : fFd(f) {}
- size_t bytesWritten() const override { return fBytesWritten; }
- bool write(const void* buffer, size_t size) override {
- fBytesWritten += size;
- return size == 0 || ::write(fFd, buffer, size) > 0;
- }
- } fdStream(fd);
- (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100);
- if (fn != NULL) {
- notifyMediaScanner(fn);
- }
- } else {
- uint32_t c = dataSpaceToInt(d);
- write(fd, &w, 4);
- write(fd, &h, 4);
- write(fd, &f, 4);
- write(fd, &c, 4);
- size_t Bpp = bytesPerPixel(f);
- for (size_t y=0 ; y<h ; y++) {
- write(fd, base, w*Bpp);
- base = (void *)((char *)base + s*Bpp);
- }
+ result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
+
+ if (base == NULL) {
+ close(fd);
+ _exit(1);
+ }
+
+ w = outBuffer->getWidth();
+ h = outBuffer->getHeight();
+ s = outBuffer->getStride();
+ f = outBuffer->getPixelFormat();
+ d = HAL_DATASPACE_UNKNOWN;
+ size = s * h * bytesPerPixel(f);
+
+ if (png) {
+ const SkImageInfo info =
+ SkImageInfo::Make(w, h, flinger2skia(f), kPremul_SkAlphaType, dataSpaceToColorSpace(d));
+ SkPixmap pixmap(info, base, s * bytesPerPixel(f));
+ struct FDWStream final : public SkWStream {
+ size_t fBytesWritten = 0;
+ int fFd;
+ FDWStream(int f) : fFd(f) {}
+ size_t bytesWritten() const override { return fBytesWritten; }
+ bool write(const void* buffer, size_t size) override {
+ fBytesWritten += size;
+ return size == 0 || ::write(fFd, buffer, size) > 0;
+ }
+ } fdStream(fd);
+ (void)SkEncodeImage(&fdStream, pixmap, SkEncodedImageFormat::kPNG, 100);
+ if (fn != NULL) {
+ notifyMediaScanner(fn);
+ }
+ } else {
+ uint32_t c = dataSpaceToInt(d);
+ write(fd, &w, 4);
+ write(fd, &h, 4);
+ write(fd, &f, 4);
+ write(fd, &c, 4);
+ size_t Bpp = bytesPerPixel(f);
+ for (size_t y=0 ; y<h ; y++) {
+ write(fd, base, w*Bpp);
+ base = (void *)((char *)base + s*Bpp);
}
}
close(fd);
@@ -253,4 +258,4 @@
// b/36066697: Avoid running static destructors.
_exit(0);
-}
+}
\ No newline at end of file
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index b26117d..d01938b 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -18,6 +18,7 @@
import android.accessibilityservice.IAccessibilityServiceClient;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.view.InputEvent;
import android.view.WindowContentFrameStats;
import android.view.WindowAnimationFrameStats;
@@ -37,7 +38,7 @@
void disconnect();
boolean injectInputEvent(in InputEvent event, boolean sync);
boolean setRotation(int rotation);
- Bitmap takeScreenshot(int width, int height);
+ Bitmap takeScreenshot(in Rect crop, int rotation);
boolean clearWindowContentFrameStats(int windowId);
WindowContentFrameStats getWindowContentFrameStats(int windowId);
void clearWindowAnimationFrameStats();
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index c99de5d..8f01685 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -26,6 +26,7 @@
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Point;
+import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManagerGlobal;
import android.os.IBinder;
@@ -690,42 +691,15 @@
.getRealDisplay(Display.DEFAULT_DISPLAY);
Point displaySize = new Point();
display.getRealSize(displaySize);
- final int displayWidth = displaySize.x;
- final int displayHeight = displaySize.y;
- final float screenshotWidth;
- final float screenshotHeight;
-
- final int rotation = display.getRotation();
- switch (rotation) {
- case ROTATION_FREEZE_0: {
- screenshotWidth = displayWidth;
- screenshotHeight = displayHeight;
- } break;
- case ROTATION_FREEZE_90: {
- screenshotWidth = displayHeight;
- screenshotHeight = displayWidth;
- } break;
- case ROTATION_FREEZE_180: {
- screenshotWidth = displayWidth;
- screenshotHeight = displayHeight;
- } break;
- case ROTATION_FREEZE_270: {
- screenshotWidth = displayHeight;
- screenshotHeight = displayWidth;
- } break;
- default: {
- throw new IllegalArgumentException("Invalid rotation: "
- + rotation);
- }
- }
+ int rotation = display.getRotation();
// Take the screenshot
Bitmap screenShot = null;
try {
// Calling out without a lock held.
- screenShot = mUiAutomationConnection.takeScreenshot((int) screenshotWidth,
- (int) screenshotHeight);
+ screenShot = mUiAutomationConnection.takeScreenshot(
+ new Rect(0, 0, displaySize.x, displaySize.y), rotation);
if (screenShot == null) {
return null;
}
@@ -734,21 +708,6 @@
return null;
}
- // Rotate the screenshot to the current orientation
- if (rotation != ROTATION_FREEZE_0) {
- Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight,
- Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(unrotatedScreenShot);
- canvas.translate(unrotatedScreenShot.getWidth() / 2,
- unrotatedScreenShot.getHeight() / 2);
- canvas.rotate(getDegreesForRotation(rotation));
- canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2);
- canvas.drawBitmap(screenShot, 0, 0, null);
- canvas.setBitmap(null);
- screenShot.recycle();
- screenShot = unrotatedScreenShot;
- }
-
// Optimization
screenShot.setHasAlpha(false);
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 5e414b8..d3828ab 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.content.pm.IPackageManager;
import android.graphics.Bitmap;
+import android.graphics.Rect;
import android.hardware.input.InputManager;
import android.os.Binder;
import android.os.IBinder;
@@ -153,7 +154,7 @@
}
@Override
- public Bitmap takeScreenshot(int width, int height) {
+ public Bitmap takeScreenshot(Rect crop, int rotation) {
synchronized (mLock) {
throwIfCalledByNotTrustedUidLocked();
throwIfShutdownLocked();
@@ -161,7 +162,9 @@
}
final long identity = Binder.clearCallingIdentity();
try {
- return SurfaceControl.screenshot(width, height);
+ int width = crop.width();
+ int height = crop.height();
+ return SurfaceControl.screenshot(crop, width, height, rotation);
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 3d01ec2..37550d8 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -16,6 +16,9 @@
package android.view;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
import android.annotation.Size;
import android.graphics.Bitmap;
import android.graphics.GraphicBuffer;
@@ -55,8 +58,6 @@
private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
boolean allLayers, boolean useIdentityTransform);
- private static native void nativeCaptureLayers(IBinder layerHandleToken, Surface consumer,
- Rect sourceCrop, float frameScale);
private static native GraphicBuffer nativeCaptureLayers(IBinder layerHandleToken,
Rect sourceCrop, float frameScale);
@@ -1144,22 +1145,35 @@
/**
* Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
- * includes all Surfaces in the screenshot.
+ * includes all Surfaces in the screenshot. This will also update the orientation so it
+ * sends the correct coordinates to SF based on the rotation value.
*
+ * @param sourceCrop The portion of the screen to capture into the Bitmap;
+ * caller may pass in 'new Rect()' if no cropping is desired.
* @param width The desired width of the returned bitmap; the raw
* screen will be scaled down to this size.
* @param height The desired height of the returned bitmap; the raw
* screen will be scaled down to this size.
+ * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
+ * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
+ * screenshots in its native portrait orientation by default, so this is
+ * useful for returning screenshots that are independent of device
+ * orientation.
* @return Returns a Bitmap containing the screen contents, or null
* if an error occurs. Make sure to call Bitmap.recycle() as soon as
* possible, once its content is not needed anymore.
*/
- public static Bitmap screenshot(int width, int height) {
+ public static Bitmap screenshot(Rect sourceCrop, int width, int height, int rotation) {
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
- return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,
- false, Surface.ROTATION_0);
+ if (rotation == ROTATION_90 || rotation == ROTATION_270) {
+ rotation = (rotation == ROTATION_90) ? ROTATION_270 : ROTATION_90;
+ }
+
+ SurfaceControl.rotateCropForSF(sourceCrop, rotation);
+ return nativeScreenshot(displayToken, sourceCrop, width, height, 0, 0, true,
+ false, rotation);
}
private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
@@ -1175,26 +1189,29 @@
minLayer, maxLayer, allLayers, useIdentityTransform);
}
+ private static void rotateCropForSF(Rect crop, int rot) {
+ if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
+ int tmp = crop.top;
+ crop.top = crop.left;
+ crop.left = tmp;
+ tmp = crop.right;
+ crop.right = crop.bottom;
+ crop.bottom = tmp;
+ }
+ }
+
/**
* Captures a layer and its children into the provided {@link Surface}.
*
* @param layerHandleToken The root layer to capture.
- * @param consumer The {@link Surface} to capture the layer into.
* @param sourceCrop The portion of the root surface to capture; caller may pass in 'new
* Rect()' or null if no cropping is desired.
* @param frameScale The desired scale of the returned buffer; the raw
* screen will be scaled up/down.
+ *
+ * @return Returns a GraphicBuffer that contains the layer capture.
*/
- public static void captureLayers(IBinder layerHandleToken, Surface consumer, Rect sourceCrop,
- float frameScale) {
- nativeCaptureLayers(layerHandleToken, consumer, sourceCrop, frameScale);
- }
-
- /**
- * Same as {@link #captureLayers(IBinder, Surface, Rect, float)} except this
- * captures to a {@link GraphicBuffer} instead of a {@link Surface}.
- */
- public static GraphicBuffer captureLayersToBuffer(IBinder layerHandleToken, Rect sourceCrop,
+ public static GraphicBuffer captureLayers(IBinder layerHandleToken, Rect sourceCrop,
float frameScale) {
return nativeCaptureLayers(layerHandleToken, sourceCrop, frameScale);
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 3ad4da6..421e0de 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -517,23 +517,7 @@
jobject graphicBuffer) {
Surface* surface = reinterpret_cast<Surface*>(nativeObject);
sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
- if (bp == nullptr) {
- return BAD_VALUE;
- }
- int err = ((ANativeWindow*)surface)->perform(surface, NATIVE_WINDOW_API_CONNECT,
- NATIVE_WINDOW_API_CPU);
- if (err != OK) {
- return err;
- }
- err = surface->attachBuffer(bp->getNativeBuffer());
- if (err != OK) {
- return err;
- }
- err = ((ANativeWindow*)surface)->queueBuffer(surface, bp->getNativeBuffer(), -1);
- if (err != OK) {
- return err;
- }
- err = surface->disconnect(NATIVE_WINDOW_API_CPU);
+ int err = Surface::attachAndQueueBuffer(surface, bp);
return err;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index f77e6c4..8c968a2 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -167,7 +167,7 @@
maxLayer = INT32_MAX;
}
sp<GraphicBuffer> buffer;
- status_t res = ScreenshotClient::captureToBuffer(displayToken,
+ status_t res = ScreenshotClient::capture(displayToken,
sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform,
rotation, &buffer);
if (res != NO_ERROR) {
@@ -201,15 +201,18 @@
maxLayer = INT32_MAX;
}
- res = screenshot->update(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
+ sp<GraphicBuffer> buffer;
+ res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
+ minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation), &buffer);
if (res != NO_ERROR) {
return NULL;
}
SkColorType colorType;
SkAlphaType alphaType;
- switch (screenshot->getFormat()) {
+
+ PixelFormat format = buffer->getPixelFormat();
+ switch (format) {
case PIXEL_FORMAT_RGBX_8888: {
colorType = kRGBA_8888_SkColorType;
alphaType = kOpaque_SkAlphaType;
@@ -235,66 +238,20 @@
}
}
- sk_sp<SkColorSpace> colorSpace;
- if (screenshot->getDataSpace() == HAL_DATASPACE_DISPLAY_P3) {
- colorSpace = SkColorSpace::MakeRGB(
- SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kDCIP3_D65_Gamut);
- } else {
- colorSpace = SkColorSpace::MakeSRGB();
- }
+ SkImageInfo info = SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
+ colorType, alphaType,
+ SkColorSpace::MakeSRGB());
- SkImageInfo screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
- screenshot->getHeight(),
- colorType,
- alphaType,
- colorSpace);
-
- const size_t rowBytes =
- screenshot->getStride() * android::bytesPerPixel(screenshot->getFormat());
-
- if (!screenshotInfo.width() || !screenshotInfo.height()) {
- return NULL;
- }
-
- auto bitmap = new Bitmap(
- (void*) screenshot->getPixels(), (void*) screenshot.get(), DeleteScreenshot,
- screenshotInfo, rowBytes);
- screenshot.release();
- bitmap->setImmutable();
- return bitmap::createBitmap(env, bitmap,
- android::bitmap::kBitmapCreateFlag_Premultiplied, NULL);
+ auto bitmap = sk_sp<Bitmap>(new Bitmap(buffer.get(), info));
+ return bitmap::createBitmap(env, bitmap.release(),
+ android::bitmap::kBitmapCreateFlag_Premultiplied, NULL);
}
static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
jobject surfaceObj, jobject sourceCropObj, jint width, jint height,
jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
- if (displayToken != NULL) {
- sp<Surface> consumer = android_view_Surface_getSurface(env, surfaceObj);
- if (consumer != NULL) {
- int left = env->GetIntField(sourceCropObj, gRectClassInfo.left);
- int top = env->GetIntField(sourceCropObj, gRectClassInfo.top);
- int right = env->GetIntField(sourceCropObj, gRectClassInfo.right);
- int bottom = env->GetIntField(sourceCropObj, gRectClassInfo.bottom);
- Rect sourceCrop(left, top, right, bottom);
-
- if (allLayers) {
- minLayer = INT32_MIN;
- maxLayer = INT32_MAX;
- }
- ScreenshotClient::capture(displayToken,
- consumer->getIGraphicBufferProducer(), sourceCrop,
- width, height, minLayer, maxLayer,
- useIdentityTransform);
- }
- }
-}
-
-static void nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
- jobject surfaceObj, jobject sourceCropObj, jfloat frameScale) {
-
- sp<IBinder> layerHandle = ibinderForJavaObject(env, layerHandleToken);
- if (layerHandle == NULL) {
+ if (displayToken == NULL) {
return;
}
@@ -308,11 +265,19 @@
sourceCrop = rectFromObj(env, sourceCropObj);
}
- ScreenshotClient::captureLayers(layerHandle, consumer->getIGraphicBufferProducer(), sourceCrop,
- frameScale);
+ if (allLayers) {
+ minLayer = INT32_MIN;
+ maxLayer = INT32_MAX;
+ }
+
+ sp<GraphicBuffer> buffer;
+ ScreenshotClient::capture(displayToken, sourceCrop, width, height, minLayer, maxLayer,
+ useIdentityTransform, 0, &buffer);
+
+ Surface::attachAndQueueBuffer(consumer.get(), buffer);
}
-static jobject nativeCaptureLayersToBuffer(JNIEnv* env, jclass clazz, jobject layerHandleToken,
+static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
jobject sourceCropObj, jfloat frameScale) {
sp<IBinder> layerHandle = ibinderForJavaObject(env, layerHandleToken);
@@ -326,8 +291,7 @@
}
sp<GraphicBuffer> buffer;
- status_t res = ScreenshotClient::captureLayersToBuffer(layerHandle, sourceCrop, frameScale,
- &buffer);
+ status_t res = ScreenshotClient::captureLayers(layerHandle, sourceCrop, frameScale, &buffer);
if (res != NO_ERROR) {
return NULL;
}
@@ -1010,10 +974,8 @@
{"nativeScreenshotToBuffer",
"(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;",
(void*)nativeScreenshotToBuffer },
- {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;F)V",
- (void*)nativeCaptureLayers },
{"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
- (void*)nativeCaptureLayersToBuffer },
+ (void*)nativeCaptureLayers },
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/packages/Shell/src/com/android/shell/Screenshooter.java b/packages/Shell/src/com/android/shell/Screenshooter.java
index 8e27edf..8e01619 100644
--- a/packages/Shell/src/com/android/shell/Screenshooter.java
+++ b/packages/Shell/src/com/android/shell/Screenshooter.java
@@ -17,12 +17,11 @@
package com.android.shell;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Point;
+import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.util.Log;
import android.view.Display;
-import android.view.Surface;
import android.view.SurfaceControl;
/**
@@ -35,18 +34,6 @@
private static final String TAG = "Screenshooter";
- /** Rotation constant: Freeze rotation to 0 degrees (natural orientation) */
- public static final int ROTATION_FREEZE_0 = Surface.ROTATION_0;
-
- /** Rotation constant: Freeze rotation to 90 degrees . */
- public static final int ROTATION_FREEZE_90 = Surface.ROTATION_90;
-
- /** Rotation constant: Freeze rotation to 180 degrees . */
- public static final int ROTATION_FREEZE_180 = Surface.ROTATION_180;
-
- /** Rotation constant: Freeze rotation to 270 degrees . */
- public static final int ROTATION_FREEZE_270 = Surface.ROTATION_270;
-
/**
* Takes a screenshot.
*
@@ -60,78 +47,21 @@
final int displayWidth = displaySize.x;
final int displayHeight = displaySize.y;
- final float screenshotWidth;
- final float screenshotHeight;
-
- final int rotation = display.getRotation();
- switch (rotation) {
- case ROTATION_FREEZE_0: {
- screenshotWidth = displayWidth;
- screenshotHeight = displayHeight;
- } break;
- case ROTATION_FREEZE_90: {
- screenshotWidth = displayHeight;
- screenshotHeight = displayWidth;
- } break;
- case ROTATION_FREEZE_180: {
- screenshotWidth = displayWidth;
- screenshotHeight = displayHeight;
- } break;
- case ROTATION_FREEZE_270: {
- screenshotWidth = displayHeight;
- screenshotHeight = displayWidth;
- } break;
- default: {
- throw new IllegalArgumentException("Invalid rotation: "
- + rotation);
- }
- }
-
+ int rotation = display.getRotation();
+ Rect crop = new Rect(0, 0, displayWidth, displayHeight);
Log.d(TAG, "Taking screenshot of dimensions " + displayWidth + " x " + displayHeight);
// Take the screenshot
Bitmap screenShot =
- SurfaceControl.screenshot((int) screenshotWidth, (int) screenshotHeight);
+ SurfaceControl.screenshot(crop, displayWidth, displayHeight, rotation);
if (screenShot == null) {
- Log.e(TAG, "Failed to take screenshot of dimensions " + screenshotWidth + " x "
- + screenshotHeight);
+ Log.e(TAG, "Failed to take screenshot of dimensions " + displayWidth + " x "
+ + displayHeight);
return null;
}
- // Rotate the screenshot to the current orientation
- if (rotation != ROTATION_FREEZE_0) {
- Bitmap unrotatedScreenShot = Bitmap.createBitmap(displayWidth, displayHeight,
- Bitmap.Config.ARGB_8888, screenShot.hasAlpha(), screenShot.getColorSpace());
- Canvas canvas = new Canvas(unrotatedScreenShot);
- canvas.translate(unrotatedScreenShot.getWidth() / 2,
- unrotatedScreenShot.getHeight() / 2);
- canvas.rotate(getDegreesForRotation(rotation));
- canvas.translate(- screenshotWidth / 2, - screenshotHeight / 2);
- canvas.drawBitmap(screenShot, 0, 0, null);
- canvas.setBitmap(null);
- screenShot.recycle();
- screenShot = unrotatedScreenShot;
- }
-
// Optimization
screenShot.setHasAlpha(false);
return screenShot;
}
-
- private static float getDegreesForRotation(int value) {
- switch (value) {
- case Surface.ROTATION_90: {
- return 360f - 90f;
- }
- case Surface.ROTATION_180: {
- return 360f - 180f;
- }
- case Surface.ROTATION_270: {
- return 360f - 270f;
- } default: {
- return 0;
- }
- }
- }
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 991c3c8..5fcd006 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -49,7 +49,6 @@
import android.media.MediaActionSound;
import android.net.Uri;
import android.os.AsyncTask;
-import android.os.Bundle;
import android.os.Environment;
import android.os.PowerManager;
import android.os.Process;
@@ -162,7 +161,7 @@
Matrix matrix = new Matrix();
int overlayColor = 0x40FFFFFF;
- Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, data.image.getConfig());
+ Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888);
matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
c.setBitmap(picture);
c.drawBitmap(data.image, matrix, paint);
@@ -171,7 +170,7 @@
// Note, we can't use the preview for the small icon, since it is non-square
float scale = (float) iconSize / Math.min(mImageWidth, mImageHeight);
- Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, data.image.getConfig());
+ Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, Bitmap.Config.ARGB_8888);
matrix.setScale(scale, scale);
matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
(iconSize - (scale * mImageHeight)) / 2);
@@ -557,25 +556,14 @@
/**
* Takes a screenshot of the current display and shows an animation.
*/
- void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible,
- int x, int y, int width, int height) {
- // We need to orient the screenshot correctly (and the Surface api seems to take screenshots
- // only in the natural orientation of the device :!)
- mDisplay.getRealMetrics(mDisplayMetrics);
- float[] dims = {mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels};
- float degrees = getDegreesForRotation(mDisplay.getRotation());
- boolean requiresRotation = (degrees > 0);
- if (requiresRotation) {
- // Get the dimensions of the device in its native orientation
- mDisplayMatrix.reset();
- mDisplayMatrix.preRotate(-degrees);
- mDisplayMatrix.mapPoints(dims);
- dims[0] = Math.abs(dims[0]);
- dims[1] = Math.abs(dims[1]);
- }
+ private void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible,
+ Rect crop) {
+ int rot = mDisplay.getRotation();
+ int width = crop.width();
+ int height = crop.height();
// Take the screenshot
- mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
+ mScreenBitmap = SurfaceControl.screenshot(crop, width, height, rot);
if (mScreenBitmap == null) {
notifyScreenshotError(mContext, mNotificationManager,
R.string.screenshot_failed_to_capture_text);
@@ -583,29 +571,6 @@
return;
}
- if (requiresRotation) {
- // Rotate the screenshot to the current orientation
- Bitmap ss = Bitmap.createBitmap(mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels, Bitmap.Config.ARGB_8888,
- mScreenBitmap.hasAlpha(), mScreenBitmap.getColorSpace());
- Canvas c = new Canvas(ss);
- c.translate(ss.getWidth() / 2, ss.getHeight() / 2);
- c.rotate(degrees);
- c.translate(-dims[0] / 2, -dims[1] / 2);
- c.drawBitmap(mScreenBitmap, 0, 0, null);
- c.setBitmap(null);
- // Recycle the previous bitmap
- mScreenBitmap.recycle();
- mScreenBitmap = ss;
- }
-
- if (width != mDisplayMetrics.widthPixels || height != mDisplayMetrics.heightPixels) {
- // Crop the screenshot to selected region
- Bitmap cropped = Bitmap.createBitmap(mScreenBitmap, x, y, width, height);
- mScreenBitmap.recycle();
- mScreenBitmap = cropped;
- }
-
// Optimizations
mScreenBitmap.setHasAlpha(false);
mScreenBitmap.prepareToDraw();
@@ -617,8 +582,8 @@
void takeScreenshot(Runnable finisher, boolean statusBarVisible, boolean navBarVisible) {
mDisplay.getRealMetrics(mDisplayMetrics);
- takeScreenshot(finisher, statusBarVisible, navBarVisible, 0, 0, mDisplayMetrics.widthPixels,
- mDisplayMetrics.heightPixels);
+ takeScreenshot(finisher, statusBarVisible, navBarVisible,
+ new Rect(0, 0, mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
}
/**
@@ -648,7 +613,7 @@
mScreenshotLayout.post(new Runnable() {
public void run() {
takeScreenshot(finisher, statusBarVisible, navBarVisible,
- rect.left, rect.top, rect.width(), rect.height());
+ rect);
}
});
}
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 84e475a..43a0893 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -226,7 +226,7 @@
final Rect taskFrame = new Rect();
task.getBounds(taskFrame);
- final GraphicBuffer buffer = SurfaceControl.captureLayersToBuffer(
+ final GraphicBuffer buffer = SurfaceControl.captureLayers(
task.getSurfaceControl().getHandle(), taskFrame, scaleFraction);
if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {