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;
     }
 
     /**