summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmds/screencap/screencap.cpp97
-rw-r--r--core/java/android/view/SurfaceControl.java16
-rw-r--r--core/jni/android_view_Surface.cpp18
-rw-r--r--core/jni/android_view_SurfaceControl.cpp92
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java4
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java2
6 files changed, 144 insertions, 85 deletions
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 31722815276c..6ded24648353 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -159,7 +159,7 @@ int main(int argc, char** argv)
void const* mapbase = MAP_FAILED;
ssize_t mapsize = -1;
- void* base = NULL;
+ void const* base = NULL;
uint32_t w, s, h, f;
android_dataspace d;
size_t size = 0;
@@ -179,6 +179,7 @@ int main(int argc, char** argv)
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);
@@ -198,57 +199,51 @@ int main(int argc, char** argv)
uint8_t displayOrientation = configs[activeConfig].orientation;
uint32_t captureOrientation = ORIENTATION_MAP[displayOrientation];
- 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);
- }
-
- result = outBuffer->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &base);
-
- if (base == NULL) {
- close(fd);
- _exit(1);
+ 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();
}
- 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);
+ 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);
+ }
}
}
close(fd);
@@ -258,4 +253,4 @@ int main(int argc, char** argv)
// b/36066697: Avoid running static destructors.
_exit(0);
-} \ No newline at end of file
+}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cf059104e373..3d01ec23b723 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -55,6 +55,8 @@ public class SurfaceControl {
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);
@@ -1177,14 +1179,22 @@ public class SurfaceControl {
* 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 GraphicBuffer captureLayers(IBinder layerHandleToken, Rect sourceCrop,
+ 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,
float frameScale) {
return nativeCaptureLayers(layerHandleToken, sourceCrop, frameScale);
}
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 421e0de52cc0..3ad4da6b6580 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -517,7 +517,23 @@ static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeOb
jobject graphicBuffer) {
Surface* surface = reinterpret_cast<Surface*>(nativeObject);
sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
- int err = Surface::attachAndQueueBuffer(surface, bp);
+ 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);
return err;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 8c968a2a7083..f77e6c4fa7b8 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -167,7 +167,7 @@ static jobject nativeScreenshotToBuffer(JNIEnv* env, jclass clazz,
maxLayer = INT32_MAX;
}
sp<GraphicBuffer> buffer;
- status_t res = ScreenshotClient::capture(displayToken,
+ status_t res = ScreenshotClient::captureToBuffer(displayToken,
sourceCrop, width, height, minLayer, maxLayer, useIdentityTransform,
rotation, &buffer);
if (res != NO_ERROR) {
@@ -201,18 +201,15 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
maxLayer = INT32_MAX;
}
- sp<GraphicBuffer> buffer;
- res = ScreenshotClient::capture(displayToken, sourceCrop, width, height,
- minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation), &buffer);
+ res = screenshot->update(displayToken, sourceCrop, width, height,
+ minLayer, maxLayer, useIdentityTransform, static_cast<uint32_t>(rotation));
if (res != NO_ERROR) {
return NULL;
}
SkColorType colorType;
SkAlphaType alphaType;
-
- PixelFormat format = buffer->getPixelFormat();
- switch (format) {
+ switch (screenshot->getFormat()) {
case PIXEL_FORMAT_RGBX_8888: {
colorType = kRGBA_8888_SkColorType;
alphaType = kOpaque_SkAlphaType;
@@ -238,20 +235,66 @@ static jobject nativeScreenshotBitmap(JNIEnv* env, jclass clazz,
}
}
- SkImageInfo info = SkImageInfo::Make(buffer->getWidth(), buffer->getHeight(),
- colorType, alphaType,
- SkColorSpace::MakeSRGB());
+ 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 screenshotInfo = SkImageInfo::Make(screenshot->getWidth(),
+ screenshot->getHeight(),
+ colorType,
+ alphaType,
+ colorSpace);
- auto bitmap = sk_sp<Bitmap>(new Bitmap(buffer.get(), info));
- return bitmap::createBitmap(env, bitmap.release(),
- android::bitmap::kBitmapCreateFlag_Premultiplied, NULL);
+ 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);
}
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) {
+ 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) {
return;
}
@@ -265,19 +308,11 @@ static void nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
sourceCrop = rectFromObj(env, sourceCropObj);
}
- 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);
+ ScreenshotClient::captureLayers(layerHandle, consumer->getIGraphicBufferProducer(), sourceCrop,
+ frameScale);
}
-static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
+static jobject nativeCaptureLayersToBuffer(JNIEnv* env, jclass clazz, jobject layerHandleToken,
jobject sourceCropObj, jfloat frameScale) {
sp<IBinder> layerHandle = ibinderForJavaObject(env, layerHandleToken);
@@ -291,7 +326,8 @@ static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandl
}
sp<GraphicBuffer> buffer;
- status_t res = ScreenshotClient::captureLayers(layerHandle, sourceCrop, frameScale, &buffer);
+ status_t res = ScreenshotClient::captureLayersToBuffer(layerHandle, sourceCrop, frameScale,
+ &buffer);
if (res != NO_ERROR) {
return NULL;
}
@@ -974,8 +1010,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
{"nativeScreenshotToBuffer",
"(Landroid/os/IBinder;Landroid/graphics/Rect;IIIIZZI)Landroid/graphics/GraphicBuffer;",
(void*)nativeScreenshotToBuffer },
- {"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
+ {"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 },
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index e9096447bbf6..991c3c83cbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -162,7 +162,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
Matrix matrix = new Matrix();
int overlayColor = 0x40FFFFFF;
- Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888);
+ Bitmap picture = Bitmap.createBitmap(previewWidth, previewHeight, data.image.getConfig());
matrix.setTranslate((previewWidth - mImageWidth) / 2, (previewHeight - mImageHeight) / 2);
c.setBitmap(picture);
c.drawBitmap(data.image, matrix, paint);
@@ -171,7 +171,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// 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, Bitmap.Config.ARGB_8888);
+ Bitmap icon = Bitmap.createBitmap(iconSize, iconSize, data.image.getConfig());
matrix.setScale(scale, scale);
matrix.postTranslate((iconSize - (scale * mImageWidth)) / 2,
(iconSize - (scale * mImageHeight)) / 2);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 43a089373a35..84e475a25187 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 @@ class TaskSnapshotController {
final Rect taskFrame = new Rect();
task.getBounds(taskFrame);
- final GraphicBuffer buffer = SurfaceControl.captureLayers(
+ final GraphicBuffer buffer = SurfaceControl.captureLayersToBuffer(
task.getSurfaceControl().getHandle(), taskFrame, scaleFraction);
if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {