Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66b5664f authored by Robert Carr's avatar Robert Carr
Browse files

Careful with screenshots containing secure layers!

For purposes of	the screen rotation animation the system server	is allowed
to capture secure (not protected) layers and trusted not to persist screenshots
which may contain secure layers. However when displaying the screen rotation animation,
the layer the screenshot is placed on will itself not be secure, so if we record
the animation the recording will contain persisted versions of the secure content. Make sure
we use the new API from SurfaceFlinger to set FLAG_SECURE if our screenshot contains secure
content.

Bug: 69703445
Test: Transaction_test#SetFlagsSecureEuidSystem
Change-Id: I1b016fb1ad56eccd712442a71cc134e5fa3b1ac6
parent 08db2662
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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.
+13 −3
Original line number Diff line number Diff line
@@ -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;
        }
    }

    /**
+5 −3
Original line number Diff line number Diff line
@@ -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");
+5 −12
Original line number Diff line number Diff line
@@ -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
+14 −1
Original line number Diff line number Diff line
@@ -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);