blob: eea6e3cb35db3adf75e5cdfd1423cf78bf3f1509 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wm.shell.common;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.view.SurfaceControl;
import java.util.function.Consumer;
/**
* Helpers for working with screenshots.
*/
public class ScreenshotUtils {
/**
* Take a screenshot of the specified SurfaceControl.
*
* @param sc the SurfaceControl to take a screenshot of
* @param crop the crop to use when capturing the screenshot
* @param consumer Consumer for the captured buffer
*/
public static void captureLayer(SurfaceControl sc, Rect crop,
Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
consumer.accept(SurfaceControl.captureLayers(
new SurfaceControl.LayerCaptureArgs.Builder(sc)
.setSourceCrop(crop)
.setCaptureSecureLayers(true)
.setAllowProtected(true)
.build()));
}
private static class BufferConsumer implements
Consumer<SurfaceControl.ScreenshotHardwareBuffer> {
SurfaceControl mScreenshot = null;
SurfaceControl.Transaction mTransaction;
SurfaceControl mSurfaceControl;
int mLayer;
BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, int layer) {
mTransaction = t;
mSurfaceControl = sc;
mLayer = layer;
}
@Override
public void accept(SurfaceControl.ScreenshotHardwareBuffer buffer) {
if (buffer == null || buffer.getHardwareBuffer() == null) {
return;
}
final GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
buffer.getHardwareBuffer());
mScreenshot = new SurfaceControl.Builder()
.setName("ScreenshotUtils screenshot")
.setFormat(PixelFormat.TRANSLUCENT)
.setSecure(buffer.containsSecureLayers())
.setCallsite("ScreenshotUtils.takeScreenshot")
.setBLASTLayer()
.build();
mTransaction.setBuffer(mScreenshot, graphicBuffer);
mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
mTransaction.reparent(mScreenshot, mSurfaceControl);
mTransaction.setLayer(mScreenshot, mLayer);
mTransaction.show(mScreenshot);
mTransaction.apply();
}
}
/**
* Take a screenshot of the specified SurfaceControl.
*
* @param t the transaction used to set changes on the resulting screenshot.
* @param sc the SurfaceControl to take a screenshot of
* @param crop the crop to use when capturing the screenshot
* @param layer the layer to place the screenshot
*
* @return A SurfaceControl where the screenshot will be attached, or null if failed.
*/
public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
Rect crop, int layer) {
BufferConsumer consumer = new BufferConsumer(t, sc, layer);
captureLayer(sc, crop, consumer);
return consumer.mScreenshot;
}
}