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