• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 android.view;
18 
19 import dalvik.system.CloseGuard;
20 import android.graphics.Bitmap;
21 import android.graphics.Rect;
22 import android.graphics.Region;
23 import android.view.Surface;
24 import android.os.IBinder;
25 import android.os.SystemProperties;
26 import android.util.Log;
27 import android.view.Surface.OutOfResourcesException;
28 
29 /**
30  * SurfaceControl
31  *  @hide
32  */
33 public class SurfaceControl {
34     private static final String TAG = "SurfaceControl";
35 
nativeCreate(SurfaceSession session, String name, int w, int h, int format, int flags)36     private static native int nativeCreate(SurfaceSession session, String name,
37             int w, int h, int format, int flags)
38             throws OutOfResourcesException;
nativeRelease(int nativeObject)39     private static native void nativeRelease(int nativeObject);
nativeDestroy(int nativeObject)40     private static native void nativeDestroy(int nativeObject);
41 
nativeScreenshot(IBinder displayToken, int width, int height, int minLayer, int maxLayer, boolean allLayers)42     private static native Bitmap nativeScreenshot(IBinder displayToken,
43             int width, int height, int minLayer, int maxLayer, boolean allLayers);
nativeScreenshot(IBinder displayToken, Surface consumer, int width, int height, int minLayer, int maxLayer, boolean allLayers)44     private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
45             int width, int height, int minLayer, int maxLayer, boolean allLayers);
46 
nativeOpenTransaction()47     private static native void nativeOpenTransaction();
nativeCloseTransaction()48     private static native void nativeCloseTransaction();
nativeSetAnimationTransaction()49     private static native void nativeSetAnimationTransaction();
50 
nativeSetLayer(int nativeObject, int zorder)51     private static native void nativeSetLayer(int nativeObject, int zorder);
nativeSetPosition(int nativeObject, float x, float y)52     private static native void nativeSetPosition(int nativeObject, float x, float y);
nativeSetSize(int nativeObject, int w, int h)53     private static native void nativeSetSize(int nativeObject, int w, int h);
nativeSetTransparentRegionHint(int nativeObject, Region region)54     private static native void nativeSetTransparentRegionHint(int nativeObject, Region region);
nativeSetAlpha(int nativeObject, float alpha)55     private static native void nativeSetAlpha(int nativeObject, float alpha);
nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy)56     private static native void nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
nativeSetFlags(int nativeObject, int flags, int mask)57     private static native void nativeSetFlags(int nativeObject, int flags, int mask);
nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b)58     private static native void nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b);
nativeSetLayerStack(int nativeObject, int layerStack)59     private static native void nativeSetLayerStack(int nativeObject, int layerStack);
60 
nativeGetBuiltInDisplay(int physicalDisplayId)61     private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
nativeCreateDisplay(String name, boolean secure)62     private static native IBinder nativeCreateDisplay(String name, boolean secure);
nativeDestroyDisplay(IBinder displayToken)63     private static native void nativeDestroyDisplay(IBinder displayToken);
nativeSetDisplaySurface( IBinder displayToken, int nativeSurfaceObject)64     private static native void nativeSetDisplaySurface(
65             IBinder displayToken, int nativeSurfaceObject);
nativeSetDisplayLayerStack( IBinder displayToken, int layerStack)66     private static native void nativeSetDisplayLayerStack(
67             IBinder displayToken, int layerStack);
nativeSetDisplayProjection( IBinder displayToken, int orientation, int l, int t, int r, int b, int L, int T, int R, int B)68     private static native void nativeSetDisplayProjection(
69             IBinder displayToken, int orientation,
70             int l, int t, int r, int b,
71             int L, int T, int R, int B);
nativeGetDisplayInfo( IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo)72     private static native boolean nativeGetDisplayInfo(
73             IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
nativeBlankDisplay(IBinder displayToken)74     private static native void nativeBlankDisplay(IBinder displayToken);
nativeUnblankDisplay(IBinder displayToken)75     private static native void nativeUnblankDisplay(IBinder displayToken);
76 
77 
78     private final CloseGuard mCloseGuard = CloseGuard.get();
79     private final String mName;
80     int mNativeObject; // package visibility only for Surface.java access
81 
82     private static final boolean HEADLESS = "1".equals(
83         SystemProperties.get("ro.config.headless", "0"));
84 
85     /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
86 
87     /**
88      * Surface creation flag: Surface is created hidden
89      */
90     public static final int HIDDEN = 0x00000004;
91 
92     /**
93      * Surface creation flag: The surface contains secure content, special
94      * measures will be taken to disallow the surface's content to be copied
95      * from another process. In particular, screenshots and VNC servers will
96      * be disabled, but other measures can take place, for instance the
97      * surface might not be hardware accelerated.
98      *
99      */
100     public static final int SECURE = 0x00000080;
101 
102     /**
103      * Surface creation flag: Creates a surface where color components are interpreted
104      * as "non pre-multiplied" by their alpha channel. Of course this flag is
105      * meaningless for surfaces without an alpha channel. By default
106      * surfaces are pre-multiplied, which means that each color component is
107      * already multiplied by its alpha value. In this case the blending
108      * equation used is:
109      *
110      *    DEST = SRC + DEST * (1-SRC_ALPHA)
111      *
112      * By contrast, non pre-multiplied surfaces use the following equation:
113      *
114      *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
115      *
116      * pre-multiplied surfaces must always be used if transparent pixels are
117      * composited on top of each-other into the surface. A pre-multiplied
118      * surface can never lower the value of the alpha component of a given
119      * pixel.
120      *
121      * In some rare situations, a non pre-multiplied surface is preferable.
122      *
123      */
124     public static final int NON_PREMULTIPLIED = 0x00000100;
125 
126     /**
127      * Surface creation flag: Indicates that the surface must be considered opaque,
128      * even if its pixel format is set to translucent. This can be useful if an
129      * application needs full RGBA 8888 support for instance but will
130      * still draw every pixel opaque.
131      *
132      */
133     public static final int OPAQUE = 0x00000400;
134 
135     /**
136      * Surface creation flag: Application requires a hardware-protected path to an
137      * external display sink. If a hardware-protected path is not available,
138      * then this surface will not be displayed on the external sink.
139      *
140      */
141     public static final int PROTECTED_APP = 0x00000800;
142 
143     // 0x1000 is reserved for an independent DRM protected flag in framework
144 
145     /**
146      * Surface creation flag: Creates a normal surface.
147      * This is the default.
148      *
149      */
150     public static final int FX_SURFACE_NORMAL   = 0x00000000;
151 
152     /**
153      * Surface creation flag: Creates a Dim surface.
154      * Everything behind this surface is dimmed by the amount specified
155      * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
156      * doesn't have a backing store.
157      *
158      */
159     public static final int FX_SURFACE_DIM = 0x00020000;
160 
161     /**
162      * Mask used for FX values above.
163      *
164      */
165     public static final int FX_SURFACE_MASK = 0x000F0000;
166 
167     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
168 
169     /**
170      * Surface flag: Hide the surface.
171      * Equivalent to calling hide().
172      */
173     public static final int SURFACE_HIDDEN = 0x01;
174 
175 
176     /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
177      * these are different from the logical display ids used elsewhere in the framework */
178 
179     /**
180      * Built-in physical display id: Main display.
181      * Use only with {@link SurfaceControl#getBuiltInDisplay()}.
182      */
183     public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
184 
185     /**
186      * Built-in physical display id: Attached HDMI display.
187      * Use only with {@link SurfaceControl#getBuiltInDisplay()}.
188      */
189     public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
190 
191 
192 
193     /**
194      * Create a surface with a name.
195      *
196      * The surface creation flags specify what kind of surface to create and
197      * certain options such as whether the surface can be assumed to be opaque
198      * and whether it should be initially hidden.  Surfaces should always be
199      * created with the {@link #HIDDEN} flag set to ensure that they are not
200      * made visible prematurely before all of the surface's properties have been
201      * configured.
202      *
203      * Good practice is to first create the surface with the {@link #HIDDEN} flag
204      * specified, open a transaction, set the surface layer, layer stack, alpha,
205      * and position, call {@link #show} if appropriate, and close the transaction.
206      *
207      * @param session The surface session, must not be null.
208      * @param name The surface name, must not be null.
209      * @param w The surface initial width.
210      * @param h The surface initial height.
211      * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
212      * in the creation flags.
213      *
214      * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
215      */
SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags)216     public SurfaceControl(SurfaceSession session,
217             String name, int w, int h, int format, int flags)
218                     throws OutOfResourcesException {
219         if (session == null) {
220             throw new IllegalArgumentException("session must not be null");
221         }
222         if (name == null) {
223             throw new IllegalArgumentException("name must not be null");
224         }
225 
226         if ((flags & SurfaceControl.HIDDEN) == 0) {
227             Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
228                     + "to ensure that they are not made visible prematurely before "
229                     + "all of the surface's properties have been configured.  "
230                     + "Set the other properties and make the surface visible within "
231                     + "a transaction.  New surface name: " + name,
232                     new Throwable());
233         }
234 
235         checkHeadless();
236 
237         mName = name;
238         mNativeObject = nativeCreate(session, name, w, h, format, flags);
239         if (mNativeObject == 0) {
240             throw new OutOfResourcesException(
241                     "Couldn't allocate SurfaceControl native object");
242         }
243 
244         mCloseGuard.open("release");
245     }
246 
247     @Override
finalize()248     protected void finalize() throws Throwable {
249         try {
250             if (mCloseGuard != null) {
251                 mCloseGuard.warnIfOpen();
252             }
253             if (mNativeObject != 0) {
254                 nativeRelease(mNativeObject);
255             }
256         } finally {
257             super.finalize();
258         }
259     }
260 
261     @Override
toString()262     public String toString() {
263         return "Surface(name=" + mName + ")";
264     }
265 
266     /**
267      * Release the local reference to the server-side surface.
268      * Always call release() when you're done with a Surface.
269      * This will make the surface invalid.
270      */
release()271     public void release() {
272         if (mNativeObject != 0) {
273             nativeRelease(mNativeObject);
274             mNativeObject = 0;
275         }
276         mCloseGuard.close();
277     }
278 
279     /**
280      * Free all server-side state associated with this surface and
281      * release this object's reference.  This method can only be
282      * called from the process that created the service.
283      */
destroy()284     public void destroy() {
285         if (mNativeObject != 0) {
286             nativeDestroy(mNativeObject);
287             mNativeObject = 0;
288         }
289         mCloseGuard.close();
290     }
291 
checkNotReleased()292     private void checkNotReleased() {
293         if (mNativeObject == 0) throw new NullPointerException(
294                 "mNativeObject is null. Have you called release() already?");
295     }
296 
297     /*
298      * set surface parameters.
299      * needs to be inside open/closeTransaction block
300      */
301 
302     /** start a transaction */
openTransaction()303     public static void openTransaction() {
304         nativeOpenTransaction();
305     }
306 
307     /** end a transaction */
closeTransaction()308     public static void closeTransaction() {
309         nativeCloseTransaction();
310     }
311 
312     /** flag the transaction as an animation */
setAnimationTransaction()313     public static void setAnimationTransaction() {
314         nativeSetAnimationTransaction();
315     }
316 
setLayer(int zorder)317     public void setLayer(int zorder) {
318         checkNotReleased();
319         nativeSetLayer(mNativeObject, zorder);
320     }
321 
setPosition(float x, float y)322     public void setPosition(float x, float y) {
323         checkNotReleased();
324         nativeSetPosition(mNativeObject, x, y);
325     }
326 
setSize(int w, int h)327     public void setSize(int w, int h) {
328         checkNotReleased();
329         nativeSetSize(mNativeObject, w, h);
330     }
331 
hide()332     public void hide() {
333         checkNotReleased();
334         nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
335     }
336 
show()337     public void show() {
338         checkNotReleased();
339         nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN);
340     }
341 
setTransparentRegionHint(Region region)342     public void setTransparentRegionHint(Region region) {
343         checkNotReleased();
344         nativeSetTransparentRegionHint(mNativeObject, region);
345     }
346 
setAlpha(float alpha)347     public void setAlpha(float alpha) {
348         checkNotReleased();
349         nativeSetAlpha(mNativeObject, alpha);
350     }
351 
setMatrix(float dsdx, float dtdx, float dsdy, float dtdy)352     public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
353         checkNotReleased();
354         nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy);
355     }
356 
setFlags(int flags, int mask)357     public void setFlags(int flags, int mask) {
358         checkNotReleased();
359         nativeSetFlags(mNativeObject, flags, mask);
360     }
361 
setWindowCrop(Rect crop)362     public void setWindowCrop(Rect crop) {
363         checkNotReleased();
364         if (crop != null) {
365             nativeSetWindowCrop(mNativeObject,
366                 crop.left, crop.top, crop.right, crop.bottom);
367         } else {
368             nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0);
369         }
370     }
371 
setLayerStack(int layerStack)372     public void setLayerStack(int layerStack) {
373         checkNotReleased();
374         nativeSetLayerStack(mNativeObject, layerStack);
375     }
376 
377     /*
378      * set display parameters.
379      * needs to be inside open/closeTransaction block
380      */
381 
382     /**
383      * Describes the properties of a physical display known to surface flinger.
384      */
385     public static final class PhysicalDisplayInfo {
386         public int width;
387         public int height;
388         public float refreshRate;
389         public float density;
390         public float xDpi;
391         public float yDpi;
392         public boolean secure;
393 
PhysicalDisplayInfo()394         public PhysicalDisplayInfo() {
395         }
396 
PhysicalDisplayInfo(PhysicalDisplayInfo other)397         public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
398             copyFrom(other);
399         }
400 
401         @Override
equals(Object o)402         public boolean equals(Object o) {
403             return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
404         }
405 
equals(PhysicalDisplayInfo other)406         public boolean equals(PhysicalDisplayInfo other) {
407             return other != null
408                     && width == other.width
409                     && height == other.height
410                     && refreshRate == other.refreshRate
411                     && density == other.density
412                     && xDpi == other.xDpi
413                     && yDpi == other.yDpi
414                     && secure == other.secure;
415         }
416 
417         @Override
hashCode()418         public int hashCode() {
419             return 0; // don't care
420         }
421 
copyFrom(PhysicalDisplayInfo other)422         public void copyFrom(PhysicalDisplayInfo other) {
423             width = other.width;
424             height = other.height;
425             refreshRate = other.refreshRate;
426             density = other.density;
427             xDpi = other.xDpi;
428             yDpi = other.yDpi;
429             secure = other.secure;
430         }
431 
432         // For debugging purposes
433         @Override
toString()434         public String toString() {
435             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
436                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
437                     + "}";
438         }
439     }
440 
unblankDisplay(IBinder displayToken)441     public static void unblankDisplay(IBinder displayToken) {
442         if (displayToken == null) {
443             throw new IllegalArgumentException("displayToken must not be null");
444         }
445         nativeUnblankDisplay(displayToken);
446     }
447 
blankDisplay(IBinder displayToken)448     public static void blankDisplay(IBinder displayToken) {
449         if (displayToken == null) {
450             throw new IllegalArgumentException("displayToken must not be null");
451         }
452         nativeBlankDisplay(displayToken);
453     }
454 
getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo)455     public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) {
456         if (displayToken == null) {
457             throw new IllegalArgumentException("displayToken must not be null");
458         }
459         if (outInfo == null) {
460             throw new IllegalArgumentException("outInfo must not be null");
461         }
462         return nativeGetDisplayInfo(displayToken, outInfo);
463     }
464 
setDisplayProjection(IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect)465     public static void setDisplayProjection(IBinder displayToken,
466             int orientation, Rect layerStackRect, Rect displayRect) {
467         if (displayToken == null) {
468             throw new IllegalArgumentException("displayToken must not be null");
469         }
470         if (layerStackRect == null) {
471             throw new IllegalArgumentException("layerStackRect must not be null");
472         }
473         if (displayRect == null) {
474             throw new IllegalArgumentException("displayRect must not be null");
475         }
476         nativeSetDisplayProjection(displayToken, orientation,
477                 layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
478                 displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
479     }
480 
setDisplayLayerStack(IBinder displayToken, int layerStack)481     public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
482         if (displayToken == null) {
483             throw new IllegalArgumentException("displayToken must not be null");
484         }
485         nativeSetDisplayLayerStack(displayToken, layerStack);
486     }
487 
setDisplaySurface(IBinder displayToken, Surface surface)488     public static void setDisplaySurface(IBinder displayToken, Surface surface) {
489         if (displayToken == null) {
490             throw new IllegalArgumentException("displayToken must not be null");
491         }
492 
493         if (surface != null) {
494             synchronized (surface.mLock) {
495                 nativeSetDisplaySurface(displayToken, surface.mNativeObject);
496             }
497         } else {
498             nativeSetDisplaySurface(displayToken, 0);
499         }
500     }
501 
createDisplay(String name, boolean secure)502     public static IBinder createDisplay(String name, boolean secure) {
503         if (name == null) {
504             throw new IllegalArgumentException("name must not be null");
505         }
506         return nativeCreateDisplay(name, secure);
507     }
508 
destroyDisplay(IBinder displayToken)509     public static void destroyDisplay(IBinder displayToken) {
510         if (displayToken == null) {
511             throw new IllegalArgumentException("displayToken must not be null");
512         }
513         nativeDestroyDisplay(displayToken);
514     }
515 
getBuiltInDisplay(int builtInDisplayId)516     public static IBinder getBuiltInDisplay(int builtInDisplayId) {
517         return nativeGetBuiltInDisplay(builtInDisplayId);
518     }
519 
520 
521     /**
522      * Copy the current screen contents into the provided {@link Surface}
523      *
524      * @param display The display to take the screenshot of.
525      * @param consumer The {@link Surface} to take the screenshot into.
526      * @param width The desired width of the returned bitmap; the raw
527      * screen will be scaled down to this size.
528      * @param height The desired height of the returned bitmap; the raw
529      * screen will be scaled down to this size.
530      * @param minLayer The lowest (bottom-most Z order) surface layer to
531      * include in the screenshot.
532      * @param maxLayer The highest (top-most Z order) surface layer to
533      * include in the screenshot.
534      */
screenshot(IBinder display, Surface consumer, int width, int height, int minLayer, int maxLayer)535     public static void screenshot(IBinder display, Surface consumer,
536             int width, int height, int minLayer, int maxLayer) {
537         screenshot(display, consumer, width, height, minLayer, maxLayer, false);
538     }
539 
540     /**
541      * Copy the current screen contents into the provided {@link Surface}
542      *
543      * @param display The display to take the screenshot of.
544      * @param consumer The {@link Surface} to take the screenshot into.
545      * @param width The desired width of the returned bitmap; the raw
546      * screen will be scaled down to this size.
547      * @param height The desired height of the returned bitmap; the raw
548      * screen will be scaled down to this size.
549      */
screenshot(IBinder display, Surface consumer, int width, int height)550     public static void screenshot(IBinder display, Surface consumer,
551             int width, int height) {
552         screenshot(display, consumer, width, height, 0, 0, true);
553     }
554 
555     /**
556      * Copy the current screen contents into the provided {@link Surface}
557      *
558      * @param display The display to take the screenshot of.
559      * @param consumer The {@link Surface} to take the screenshot into.
560      */
screenshot(IBinder display, Surface consumer)561     public static void screenshot(IBinder display, Surface consumer) {
562         screenshot(display, consumer, 0, 0, 0, 0, true);
563     }
564 
565 
566     /**
567      * Copy the current screen contents into a bitmap and return it.
568      *
569      * CAVEAT: Versions of screenshot that return a {@link Bitmap} can
570      * be extremely slow; avoid use unless absolutely necessary; prefer
571      * the versions that use a {@link Surface} instead, such as
572      * {@link SurfaceControl#screenshot(IBinder, Surface)}.
573      *
574      * @param width The desired width of the returned bitmap; the raw
575      * screen will be scaled down to this size.
576      * @param height The desired height of the returned bitmap; the raw
577      * screen will be scaled down to this size.
578      * @param minLayer The lowest (bottom-most Z order) surface layer to
579      * include in the screenshot.
580      * @param maxLayer The highest (top-most Z order) surface layer to
581      * include in the screenshot.
582      * @return Returns a Bitmap containing the screen contents, or null
583      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
584      * possible, once its content is not needed anymore.
585      */
screenshot(int width, int height, int minLayer, int maxLayer)586     public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
587         // TODO: should take the display as a parameter
588         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
589                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
590         return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
591     }
592 
593     /**
594      * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
595      * Surfaces in the screenshot.
596      *
597      * @param width The desired width of the returned bitmap; the raw
598      * screen will be scaled down to this size.
599      * @param height The desired height of the returned bitmap; the raw
600      * screen will be scaled down to this size.
601      * @return Returns a Bitmap containing the screen contents, or null
602      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
603      * possible, once its content is not needed anymore.
604      */
screenshot(int width, int height)605     public static Bitmap screenshot(int width, int height) {
606         // TODO: should take the display as a parameter
607         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
608                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
609         return nativeScreenshot(displayToken, width, height, 0, 0, true);
610     }
611 
screenshot(IBinder display, Surface consumer, int width, int height, int minLayer, int maxLayer, boolean allLayers)612     private static void screenshot(IBinder display, Surface consumer,
613             int width, int height, int minLayer, int maxLayer, boolean allLayers) {
614         if (display == null) {
615             throw new IllegalArgumentException("displayToken must not be null");
616         }
617         if (consumer == null) {
618             throw new IllegalArgumentException("consumer must not be null");
619         }
620         nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers);
621     }
622 
checkHeadless()623     private static void checkHeadless() {
624         if (HEADLESS) {
625             throw new UnsupportedOperationException("Device is headless");
626         }
627     }
628 }
629