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