• 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 import android.window.ScreenCapture;
23 
24 import java.util.function.Consumer;
25 
26 /**
27  * Helpers for working with screenshots.
28  */
29 public class ScreenshotUtils {
30 
31     /**
32      * Takes a screenshot of the specified SurfaceControl.
33      *
34      * @param sc the SurfaceControl to take a screenshot of
35      * @param crop the crop to use when capturing the screenshot
36      * @param consumer Consumer for the captured buffer
37      */
captureLayer(SurfaceControl sc, Rect crop, Consumer<ScreenCapture.ScreenshotHardwareBuffer> consumer)38     public static void captureLayer(SurfaceControl sc, Rect crop,
39             Consumer<ScreenCapture.ScreenshotHardwareBuffer> consumer) {
40         consumer.accept(ScreenCapture.captureLayers(
41                 new ScreenCapture.LayerCaptureArgs.Builder(sc)
42                     .setSourceCrop(crop)
43                     .setCaptureSecureLayers(true)
44                     .setAllowProtected(true)
45                     .setHintForSeamlessTransition(true)
46                     .build()));
47     }
48 
49     private static class BufferConsumer implements
50             Consumer<ScreenCapture.ScreenshotHardwareBuffer> {
51         SurfaceControl mScreenshot = null;
52         SurfaceControl.Transaction mTransaction;
53         SurfaceControl mSurfaceControl;
54         SurfaceControl mParentSurfaceControl;
55         int mLayer;
56 
BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc, int layer)57         BufferConsumer(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc,
58                 int layer) {
59             mTransaction = t;
60             mSurfaceControl = sc;
61             mParentSurfaceControl = parentSc;
62             mLayer = layer;
63         }
64 
65         @Override
accept(ScreenCapture.ScreenshotHardwareBuffer buffer)66         public void accept(ScreenCapture.ScreenshotHardwareBuffer buffer) {
67             if (buffer == null || buffer.getHardwareBuffer() == null) {
68                 return;
69             }
70             mScreenshot = new SurfaceControl.Builder()
71                 .setName("ScreenshotUtils screenshot")
72                 .setFormat(PixelFormat.TRANSLUCENT)
73                 .setSecure(buffer.containsSecureLayers())
74                 .setCallsite("ScreenshotUtils.takeScreenshot")
75                 .setBLASTLayer()
76                 .build();
77 
78             mTransaction.setBuffer(mScreenshot, buffer.getHardwareBuffer());
79             mTransaction.setColorSpace(mScreenshot, buffer.getColorSpace());
80             mTransaction.reparent(mScreenshot, mParentSurfaceControl);
81             mTransaction.setLayer(mScreenshot, mLayer);
82             if (buffer.containsHdrLayers()) {
83                 mTransaction.setDimmingEnabled(mScreenshot, false);
84             }
85             mTransaction.show(mScreenshot);
86             mTransaction.apply();
87         }
88     }
89 
90     /**
91      * Takes a screenshot of the specified SurfaceControl.
92      *
93      * @param t the transaction used to set changes on the resulting screenshot.
94      * @param sc the SurfaceControl to take a screenshot of
95      * @param crop the crop to use when capturing the screenshot
96      * @param layer the layer to place the screenshot
97      *
98      * @return A SurfaceControl where the screenshot will be attached, or null if failed.
99      */
takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc, Rect crop, int layer)100     public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
101             Rect crop, int layer) {
102         return takeScreenshot(t, sc, sc /* parentSc */, crop, layer);
103     }
104 
105     /**
106      * Takes a screenshot of the specified SurfaceControl.
107      *
108      * @param t the transaction used to set changes on the resulting screenshot.
109      * @param sc the SurfaceControl to take a screenshot of
110      * @param parentSc  the SurfaceControl to attach the screenshot to.
111      * @param crop the crop to use when capturing the screenshot
112      * @param layer the layer to place the screenshot
113      *
114      * @return A SurfaceControl where the screenshot will be attached, or null if failed.
115      */
takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc, SurfaceControl parentSc, Rect crop, int layer)116     public static SurfaceControl takeScreenshot(SurfaceControl.Transaction t, SurfaceControl sc,
117             SurfaceControl parentSc, Rect crop, int layer) {
118         BufferConsumer consumer = new BufferConsumer(t, sc, parentSc, layer);
119         captureLayer(sc, crop, consumer);
120         return consumer.mScreenshot;
121     }
122 }
123