Merge "Careful with screenshots containing secure layers!" into qt-dev am: f8f5f0290e
am: cea68c7904
Change-Id: Ia2649df1fe70cc01b1544de9f6f22010c932f220
This commit is contained in:
@@ -25,6 +25,7 @@ import android.util.SparseArray;
|
||||
import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
|
||||
/**
|
||||
@@ -64,13 +65,12 @@ public abstract class DisplayManagerInternal {
|
||||
public abstract boolean isProximitySensorAvailable();
|
||||
|
||||
/**
|
||||
* Take a screenshot of the specified display into the provided {@link Surface}.
|
||||
* Take a screenshot of the specified display and return a buffer.
|
||||
*
|
||||
* @param displayId The display id to take the screenshot of.
|
||||
* @param outSurface The {@link Surface} to take the screenshot into.
|
||||
* @return True if the screenshot is taken.
|
||||
* @return The buffer or null if we have failed.
|
||||
*/
|
||||
public abstract boolean screenshot(int displayId, Surface outSurface);
|
||||
public abstract SurfaceControl.ScreenshotGraphicBuffer screenshot(int displayId);
|
||||
|
||||
/**
|
||||
* Returns information about the specified logical display.
|
||||
|
||||
@@ -439,10 +439,13 @@ public final class SurfaceControl implements Parcelable {
|
||||
public static class ScreenshotGraphicBuffer {
|
||||
private final GraphicBuffer mGraphicBuffer;
|
||||
private final ColorSpace mColorSpace;
|
||||
private final boolean mContainsSecureLayers;
|
||||
|
||||
public ScreenshotGraphicBuffer(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
|
||||
public ScreenshotGraphicBuffer(GraphicBuffer graphicBuffer, ColorSpace colorSpace,
|
||||
boolean containsSecureLayers) {
|
||||
mGraphicBuffer = graphicBuffer;
|
||||
mColorSpace = colorSpace;
|
||||
mContainsSecureLayers = containsSecureLayers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -453,13 +456,16 @@ public final class SurfaceControl implements Parcelable {
|
||||
* @param usage Hint indicating how the buffer will be used
|
||||
* @param unwrappedNativeObject The native object of GraphicBuffer
|
||||
* @param namedColorSpace Integer value of a named color space {@link ColorSpace.Named}
|
||||
* @param containsSecureLayer Indicates whether this graphic buffer contains captured contents
|
||||
* of secure layers, in which case the screenshot should not be persisted.
|
||||
*/
|
||||
private static ScreenshotGraphicBuffer createFromNative(int width, int height, int format,
|
||||
int usage, long unwrappedNativeObject, int namedColorSpace) {
|
||||
int usage, long unwrappedNativeObject, int namedColorSpace,
|
||||
boolean containsSecureLayers) {
|
||||
GraphicBuffer graphicBuffer = GraphicBuffer.createFromExisting(width, height, format,
|
||||
usage, unwrappedNativeObject);
|
||||
ColorSpace colorSpace = ColorSpace.get(ColorSpace.Named.values()[namedColorSpace]);
|
||||
return new ScreenshotGraphicBuffer(graphicBuffer, colorSpace);
|
||||
return new ScreenshotGraphicBuffer(graphicBuffer, colorSpace, containsSecureLayers);
|
||||
}
|
||||
|
||||
public ColorSpace getColorSpace() {
|
||||
@@ -469,6 +475,10 @@ public final class SurfaceControl implements Parcelable {
|
||||
public GraphicBuffer getGraphicBuffer() {
|
||||
return mGraphicBuffer;
|
||||
}
|
||||
|
||||
public boolean containsSecureLayers() {
|
||||
return mContainsSecureLayers;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -250,10 +250,11 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
|
||||
|
||||
Rect sourceCrop = rectFromObj(env, sourceCropObj);
|
||||
sp<GraphicBuffer> buffer;
|
||||
bool capturedSecureLayers = false;
|
||||
status_t res = ScreenshotClient::capture(displayToken, dataspace,
|
||||
ui::PixelFormat::RGBA_8888,
|
||||
sourceCrop, width, height,
|
||||
useIdentityTransform, rotation, captureSecureLayers, &buffer);
|
||||
useIdentityTransform, rotation, captureSecureLayers, &buffer, capturedSecureLayers);
|
||||
if (res != NO_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -266,7 +267,8 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
|
||||
buffer->getPixelFormat(),
|
||||
(jint)buffer->getUsage(),
|
||||
(jlong)buffer.get(),
|
||||
namedColorSpace);
|
||||
namedColorSpace,
|
||||
capturedSecureLayers);
|
||||
}
|
||||
|
||||
static jobject nativeCaptureLayers(JNIEnv* env, jclass clazz, jobject layerHandleToken,
|
||||
@@ -1455,7 +1457,7 @@ int register_android_view_SurfaceControl(JNIEnv* env)
|
||||
MakeGlobalRefOrDie(env, screenshotGraphicsBufferClazz);
|
||||
gScreenshotGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env,
|
||||
screenshotGraphicsBufferClazz,
|
||||
"createFromNative", "(IIIIJI)Landroid/view/SurfaceControl$ScreenshotGraphicBuffer;");
|
||||
"createFromNative", "(IIIIJIZ)Landroid/view/SurfaceControl$ScreenshotGraphicBuffer;");
|
||||
|
||||
jclass displayedContentSampleClazz = FindClassOrDie(env,
|
||||
"android/hardware/display/DisplayedContentSample");
|
||||
|
||||
@@ -1269,21 +1269,14 @@ public final class DisplayManagerService extends SystemService {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean screenshotInternal(int displayId, Surface outSurface) {
|
||||
private SurfaceControl.ScreenshotGraphicBuffer screenshotInternal(int displayId) {
|
||||
final IBinder token = getDisplayToken(displayId);
|
||||
if (token == null) {
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
final SurfaceControl.ScreenshotGraphicBuffer gb =
|
||||
SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(
|
||||
return SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(
|
||||
token, new Rect(), 0 /* width */, 0 /* height */,
|
||||
false /* useIdentityTransform */, 0 /* rotation */);
|
||||
try {
|
||||
outSurface.attachAndQueueBuffer(gb.getGraphicBuffer());
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "Failed to take screenshot - " + e.getMessage());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -2354,8 +2347,8 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean screenshot(int displayId, Surface outSurface) {
|
||||
return screenshotInternal(displayId, outSurface);
|
||||
public SurfaceControl.ScreenshotGraphicBuffer screenshot(int displayId) {
|
||||
return screenshotInternal(displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -275,7 +275,20 @@ class ScreenRotationAnimation {
|
||||
final int displayId = display.getDisplayId();
|
||||
final Surface surface = mService.mSurfaceFactory.make();
|
||||
surface.copyFrom(mSurfaceControl);
|
||||
if (mService.mDisplayManagerInternal.screenshot(displayId, surface)) {
|
||||
SurfaceControl.ScreenshotGraphicBuffer gb =
|
||||
mService.mDisplayManagerInternal.screenshot(displayId);
|
||||
if (gb != null) {
|
||||
try {
|
||||
surface.attachAndQueueBuffer(gb.getGraphicBuffer());
|
||||
} catch (RuntimeException e) {
|
||||
Slog.w(TAG, "Failed to attach screenshot - " + e.getMessage());
|
||||
}
|
||||
// If the screenshot contains secure layers, we have to make sure the
|
||||
// screenshot surface we display it in also has FLAG_SECURE so that
|
||||
// the user can not screenshot secure layers via the screenshot surface.
|
||||
if (gb.containsSecureLayers()) {
|
||||
t.setSecure(mSurfaceControl, true);
|
||||
}
|
||||
t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
|
||||
t.setAlpha(mSurfaceControl, 0);
|
||||
t.show(mSurfaceControl);
|
||||
|
||||
Reference in New Issue
Block a user