• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.wm.shell.common;
18 
19 import android.graphics.PixelFormat;
20 import android.graphics.Rect;
21 import android.view.SurfaceControl;
22 
23 import java.util.function.Consumer;
24 
25 /**
26  * Helpers for working with screenshots.
27  */
28 public class ScreenshotUtils {
29 
30     /**
31      * Takes a screenshot of the specified SurfaceControl.
32      *
33      * @param sc the SurfaceControl to take a screenshot of
34      * @param crop the crop to use when capturing the screenshot
35      * @param consumer Consumer for the captured buffer
36      */
captureLayer(SurfaceControl sc, Rect crop, Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer)37     public static void captureLayer(SurfaceControl sc, Rect crop,
38             Consumer<SurfaceControl.ScreenshotHardwareBuffer> consumer) {
39         consumer.accept(SurfaceControl.captureLayers(
40                 new SurfaceControl.LayerCaptureArgs.Builder(sc)
41                     .setSourceCrop(crop)
42                     .setCaptureSecureLayers(true)
43                     .setAllowProtected(true)
44                     .build()));
45     }
46 
47     private static class BufferConsumer implements
48             Consumer<SurfaceControl.ScreenshotHardwareBuffer> {
49         SurfaceControl mScreenshot = null;
50         SurfaceControl.Transaction mTransaction;
51         SurfaceControl mSurfaceControl;
52         SurfaceControl mParentSurfaceControl;
53         int mLayer;
54 
BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc, int layer)55         BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc,
56                 int layer) {
57             mTransaction = t;
58             mSurfaceControl = sc;
59             mParentSurfaceControl = parentSc;
60             mLayer = layer;
61         }
62 
63         @Override
accept(SurfaceControl.ScreenshotHardwareBuffer buffer)64         public void accept(SurfaceControl.ScreenshotHardwareBuffer buffer) {
65             if (buffer == null || buffer.getHardwareBuffer() == null) {
66                 return;
67             }
68             mScreenshot = new SurfaceControl.Builder()
69                 .setName("ScreenshotUtils screenshot")
70                 .setFormat(PixelFormat.TRANSLUCENT)
71                 .setSecure(buffer.containsSecureLayers())
72                 .setCallsite("ScreenshotUtils.takeScreenshot")
73                 .setBLASTLayer()
74                 .build();
75 
76             mTransaction.setBuffer(mScreenshot, buffer.getHardwareBuffer());
77             mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
78             mTransaction.reparent(mScreenshot, mParentSurfaceControl);
79             mTransaction.setLayer(mScreenshot, mLayer);
80             mTransaction.show(mScreenshot);
81             mTransaction.apply();
82         }
83     }
84 
85     /**
86      * Takes a screenshot of the specified SurfaceControl.
87      *
88      * @param t the transaction used to set changes on the resulting screenshot.
89      * @param sc the SurfaceControl to take a screenshot of
90      * @param crop the crop to use when capturing the screenshot
91      * @param layer the layer to place the screenshot
92      *
93      * @return A SurfaceControl where the screenshot will be attached, or null if failed.
94      */
takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc, Rect crop, int layer)95     public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
96             Rect crop, int layer) {
97         return takeScreenshot(t, sc, sc /* parentSc */, crop, layer);
98     }
99 
100     /**
101      * Takes a screenshot of the specified SurfaceControl.
102      *
103      * @param t the transaction used to set changes on the resulting screenshot.
104      * @param sc the SurfaceControl to take a screenshot of
105      * @param parentSc  the SurfaceControl to attach the screenshot to.
106      * @param crop the crop to use when capturing the screenshot
107      * @param layer the layer to place the screenshot
108      *
109      * @return A SurfaceControl where the screenshot will be attached, or null if failed.
110      */
takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc, Rect crop, int layer)111     public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
112             SurfaceControl parentSc, Rect crop, int layer) {
113         BufferConsumer consumer = new BufferConsumer(t, sc, parentSc, layer);
114         captureLayer(sc, crop, consumer);
115         return consumer.mScreenshot;
116     }
117 }
118