am 4b7c14bf: Merge "Use surfaceflinger for recents thumbnail rotations." into lmp-dev
* commit '4b7c14bf1cb62c806223b12fdf3c5ba1d48908e7':
Use surfaceflinger for recents thumbnail rotations.
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 1e28e33..4074529 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -39,7 +39,7 @@
private static native Bitmap nativeScreenshot(IBinder displayToken,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
- boolean allLayers, boolean useIdentityTransform);
+ boolean allLayers, boolean useIdentityTransform, int rotation);
private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
boolean allLayers, boolean useIdentityTransform);
@@ -688,17 +688,23 @@
* @param useIdentityTransform Replace whatever transformation (rotation,
* scaling, translation) the surface layers are currently using with the
* identity transformation while taking the screenshot.
+ * @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(Rect sourceCrop, int width, int height,
- int minLayer, int maxLayer, boolean useIdentityTransform) {
+ int minLayer, int maxLayer, boolean useIdentityTransform,
+ int rotation) {
// TODO: should take the display as a parameter
IBinder displayToken = SurfaceControl.getBuiltInDisplay(
SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
return nativeScreenshot(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, false, useIdentityTransform);
+ minLayer, maxLayer, false, useIdentityTransform, rotation);
}
/**
@@ -717,7 +723,8 @@
// 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);
+ return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,
+ false, Surface.ROTATION_0);
}
private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 8f30f5d..06c22ae 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -117,7 +117,8 @@
static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform) {
+ jint minLayer, jint maxLayer, bool allLayers, bool useIdentityTransform,
+ int rotation) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken == NULL) {
return NULL;
@@ -131,17 +132,13 @@
SkAutoTDelete<ScreenshotClient> screenshot(new ScreenshotClient());
status_t res;
- if (width > 0 && height > 0) {
- if (allLayers) {
- res = screenshot->update(displayToken, sourceCrop, width, height,
- useIdentityTransform);
- } else {
- res = screenshot->update(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, useIdentityTransform);
- }
- } else {
- res = screenshot->update(displayToken, sourceCrop, useIdentityTransform);
+ if (allLayers) {
+ minLayer = 0;
+ maxLayer = -1UL;
}
+
+ res = screenshot->update(displayToken, sourceCrop, width, height,
+ minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
if (res != NO_ERROR) {
return NULL;
}
@@ -588,7 +585,7 @@
(void*)nativeRelease },
{"nativeDestroy", "(J)V",
(void*)nativeDestroy },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZ)Landroid/graphics/Bitmap;",
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/Bitmap;",
(void*)nativeScreenshotBitmap },
{"nativeScreenshot", "(Landroid/os/IBinder;Landroid/view/Surface;Landroid/graphics/Rect;IIIIZZ)V",
(void*)nativeScreenshot },
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 434e48f..10ab6b5 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -5931,7 +5931,7 @@
@Override
public Bitmap screenshotApplications(IBinder appToken, int displayId, int width,
int height, boolean force565) {
- if (!checkCallingPermission(android.Manifest.permission.READ_FRAME_BUFFER,
+ if (!checkCallingPermission(Manifest.permission.READ_FRAME_BUFFER,
"screenshotApplications()")) {
throw new SecurityException("Requires READ_FRAME_BUFFER permission");
}
@@ -5951,7 +5951,7 @@
return null;
}
- Bitmap rawss = null;
+ Bitmap bm = null;
int maxLayer = 0;
final Rect frame = new Rect();
@@ -6092,10 +6092,8 @@
// The screenshot API does not apply the current screen rotation.
rot = getDefaultDisplayContentLocked().getDisplay().getRotation();
+
if (rot == Surface.ROTATION_90 || rot == Surface.ROTATION_270) {
- final int tmp = width;
- width = height;
- height = tmp;
rot = (rot == Surface.ROTATION_90) ? Surface.ROTATION_270 : Surface.ROTATION_90;
}
@@ -6121,9 +6119,9 @@
if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG,
"Taking screenshot while rotating");
- rawss = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
- inRotation);
- if (rawss == null) {
+ bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
+ inRotation, rot);
+ if (bm == null) {
Slog.w(TAG, "Screenshot failure taking screenshot for (" + dw + "x" + dh
+ ") to layer " + maxLayer);
return null;
@@ -6133,17 +6131,6 @@
break;
}
- Bitmap bm = Bitmap.createBitmap(width, height, force565 ?
- Config.RGB_565 : rawss.getConfig());
- if (DEBUG_SCREENSHOT) {
- bm.eraseColor(0xFF000000);
- }
- Matrix matrix = new Matrix();
- ScreenRotationAnimation.createRotationMatrix(rot, width, height, matrix);
- Canvas canvas = new Canvas(bm);
- canvas.drawBitmap(rawss, matrix, null);
- canvas.setBitmap(null);
-
if (DEBUG_SCREENSHOT) {
// TEST IF IT's ALL BLACK
int[] buffer = new int[bm.getWidth() * bm.getHeight()];
@@ -6164,9 +6151,12 @@
}
}
- rawss.recycle();
-
- return bm;
+ // Copy the screenshot bitmap to another buffer so that the gralloc backed
+ // bitmap will not have a long lifetime. Gralloc memory can be pinned or
+ // duplicated and might have a higher cost than a skia backed buffer.
+ Bitmap ret = bm.copy(bm.getConfig(),true);
+ bm.recycle();
+ return ret;
}
/**