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 dalvik.system.CloseGuard;
20import android.graphics.Bitmap;
21import android.graphics.Rect;
22import android.graphics.Region;
23import android.os.IBinder;
24import android.util.Log;
25import android.view.Surface.OutOfResourcesException;
26
27/**
28 * SurfaceControl
29 *  @hide
30 */
31public class SurfaceControl {
32    private static final String TAG = "SurfaceControl";
33
34    private static native long nativeCreate(SurfaceSession session, String name,
35            int w, int h, int format, int flags)
36            throws OutOfResourcesException;
37    private static native void nativeRelease(long nativeObject);
38    private static native void nativeDestroy(long nativeObject);
39
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);
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
47    private static native void nativeOpenTransaction();
48    private static native void nativeCloseTransaction();
49    private static native void nativeSetAnimationTransaction();
50
51    private static native void nativeSetLayer(long nativeObject, int zorder);
52    private static native void nativeSetPosition(long nativeObject, float x, float y);
53    private static native void nativeSetSize(long nativeObject, int w, int h);
54    private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
55    private static native void nativeSetAlpha(long nativeObject, float alpha);
56    private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
57    private static native void nativeSetFlags(long nativeObject, int flags, int mask);
58    private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
59    private static native void nativeSetLayerStack(long nativeObject, int layerStack);
60
61    private static native boolean nativeClearContentFrameStats(long nativeObject);
62    private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
63    private static native boolean nativeClearAnimationFrameStats();
64    private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
65
66    private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
67    private static native IBinder nativeCreateDisplay(String name, boolean secure);
68    private static native void nativeDestroyDisplay(IBinder displayToken);
69    private static native void nativeSetDisplaySurface(
70            IBinder displayToken, long nativeSurfaceObject);
71    private static native void nativeSetDisplayLayerStack(
72            IBinder displayToken, int layerStack);
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);
77    private static native void nativeSetDisplaySize(IBinder displayToken, int width, int height);
78    private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
79            IBinder displayToken);
80    private static native int nativeGetActiveConfig(IBinder displayToken);
81    private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
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     */
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
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
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     */
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     */
333    public void destroy() {
334        if (mNativeObject != 0) {
335            nativeDestroy(mNativeObject);
336            mNativeObject = 0;
337        }
338        mCloseGuard.close();
339    }
340
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 */
352    public static void openTransaction() {
353        nativeOpenTransaction();
354    }
355
356    /** end a transaction */
357    public static void closeTransaction() {
358        nativeCloseTransaction();
359    }
360
361    /** flag the transaction as an animation */
362    public static void setAnimationTransaction() {
363        nativeSetAnimationTransaction();
364    }
365
366    public void setLayer(int zorder) {
367        checkNotReleased();
368        nativeSetLayer(mNativeObject, zorder);
369    }
370
371    public void setPosition(float x, float y) {
372        checkNotReleased();
373        nativeSetPosition(mNativeObject, x, y);
374    }
375
376    public void setSize(int w, int h) {
377        checkNotReleased();
378        nativeSetSize(mNativeObject, w, h);
379    }
380
381    public void hide() {
382        checkNotReleased();
383        nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
384    }
385
386    public void show() {
387        checkNotReleased();
388        nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN);
389    }
390
391    public void setTransparentRegionHint(Region region) {
392        checkNotReleased();
393        nativeSetTransparentRegionHint(mNativeObject, region);
394    }
395
396    public boolean clearContentFrameStats() {
397        checkNotReleased();
398        return nativeClearContentFrameStats(mNativeObject);
399    }
400
401    public boolean getContentFrameStats(WindowContentFrameStats outStats) {
402        checkNotReleased();
403        return nativeGetContentFrameStats(mNativeObject, outStats);
404    }
405
406    public static boolean clearAnimationFrameStats() {
407        return nativeClearAnimationFrameStats();
408    }
409
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     */
418    public void setAlpha(float alpha) {
419        checkNotReleased();
420        nativeSetAlpha(mNativeObject, alpha);
421    }
422
423    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
424        checkNotReleased();
425        nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy);
426    }
427
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
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     */
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     * Sets the security of the surface.  Setting the flag is equivalent to creating the
458     * Surface with the {@link #SECURE} flag.
459     */
460    public void setSecure(boolean isSecure) {
461        checkNotReleased();
462        if (isSecure) {
463            nativeSetFlags(mNativeObject, SECURE, SECURE);
464        } else {
465            nativeSetFlags(mNativeObject, 0, SECURE);
466        }
467    }
468
469    /*
470     * set display parameters.
471     * needs to be inside open/closeTransaction block
472     */
473
474    /**
475     * Describes the properties of a physical display known to surface flinger.
476     */
477    public static final class PhysicalDisplayInfo {
478        public int width;
479        public int height;
480        public float refreshRate;
481        public float density;
482        public float xDpi;
483        public float yDpi;
484        public boolean secure;
485        public long appVsyncOffsetNanos;
486        public long presentationDeadlineNanos;
487        public int colorTransform;
488
489        public PhysicalDisplayInfo() {
490        }
491
492        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
493            copyFrom(other);
494        }
495
496        @Override
497        public boolean equals(Object o) {
498            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
499        }
500
501        public boolean equals(PhysicalDisplayInfo other) {
502            return other != null
503                    && width == other.width
504                    && height == other.height
505                    && refreshRate == other.refreshRate
506                    && density == other.density
507                    && xDpi == other.xDpi
508                    && yDpi == other.yDpi
509                    && secure == other.secure
510                    && appVsyncOffsetNanos == other.appVsyncOffsetNanos
511                    && presentationDeadlineNanos == other.presentationDeadlineNanos
512                    && colorTransform == other.colorTransform;
513        }
514
515        @Override
516        public int hashCode() {
517            return 0; // don't care
518        }
519
520        public void copyFrom(PhysicalDisplayInfo other) {
521            width = other.width;
522            height = other.height;
523            refreshRate = other.refreshRate;
524            density = other.density;
525            xDpi = other.xDpi;
526            yDpi = other.yDpi;
527            secure = other.secure;
528            appVsyncOffsetNanos = other.appVsyncOffsetNanos;
529            presentationDeadlineNanos = other.presentationDeadlineNanos;
530            colorTransform = other.colorTransform;
531        }
532
533        // For debugging purposes
534        @Override
535        public String toString() {
536            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
537                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
538                    + ", appVsyncOffset " + appVsyncOffsetNanos
539                    + ", bufferDeadline " + presentationDeadlineNanos
540                    + ", colorTransform " + colorTransform + "}";
541        }
542    }
543
544    public static void setDisplayPowerMode(IBinder displayToken, int mode) {
545        if (displayToken == null) {
546            throw new IllegalArgumentException("displayToken must not be null");
547        }
548        nativeSetDisplayPowerMode(displayToken, mode);
549    }
550
551    public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
552        if (displayToken == null) {
553            throw new IllegalArgumentException("displayToken must not be null");
554        }
555        return nativeGetDisplayConfigs(displayToken);
556    }
557
558    public static int getActiveConfig(IBinder displayToken) {
559        if (displayToken == null) {
560            throw new IllegalArgumentException("displayToken must not be null");
561        }
562        return nativeGetActiveConfig(displayToken);
563    }
564
565    public static boolean setActiveConfig(IBinder displayToken, int id) {
566        if (displayToken == null) {
567            throw new IllegalArgumentException("displayToken must not be null");
568        }
569        return nativeSetActiveConfig(displayToken, id);
570    }
571
572    public static void setDisplayProjection(IBinder displayToken,
573            int orientation, Rect layerStackRect, Rect displayRect) {
574        if (displayToken == null) {
575            throw new IllegalArgumentException("displayToken must not be null");
576        }
577        if (layerStackRect == null) {
578            throw new IllegalArgumentException("layerStackRect must not be null");
579        }
580        if (displayRect == null) {
581            throw new IllegalArgumentException("displayRect must not be null");
582        }
583        nativeSetDisplayProjection(displayToken, orientation,
584                layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
585                displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
586    }
587
588    public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
589        if (displayToken == null) {
590            throw new IllegalArgumentException("displayToken must not be null");
591        }
592        nativeSetDisplayLayerStack(displayToken, layerStack);
593    }
594
595    public static void setDisplaySurface(IBinder displayToken, Surface surface) {
596        if (displayToken == null) {
597            throw new IllegalArgumentException("displayToken must not be null");
598        }
599
600        if (surface != null) {
601            synchronized (surface.mLock) {
602                nativeSetDisplaySurface(displayToken, surface.mNativeObject);
603            }
604        } else {
605            nativeSetDisplaySurface(displayToken, 0);
606        }
607    }
608
609    public static void setDisplaySize(IBinder displayToken, int width, int height) {
610        if (displayToken == null) {
611            throw new IllegalArgumentException("displayToken must not be null");
612        }
613        if (width <= 0 || height <= 0) {
614            throw new IllegalArgumentException("width and height must be positive");
615        }
616
617        nativeSetDisplaySize(displayToken, width, height);
618    }
619
620    public static IBinder createDisplay(String name, boolean secure) {
621        if (name == null) {
622            throw new IllegalArgumentException("name must not be null");
623        }
624        return nativeCreateDisplay(name, secure);
625    }
626
627    public static void destroyDisplay(IBinder displayToken) {
628        if (displayToken == null) {
629            throw new IllegalArgumentException("displayToken must not be null");
630        }
631        nativeDestroyDisplay(displayToken);
632    }
633
634    public static IBinder getBuiltInDisplay(int builtInDisplayId) {
635        return nativeGetBuiltInDisplay(builtInDisplayId);
636    }
637
638    /**
639     * Copy the current screen contents into the provided {@link Surface}
640     *
641     * @param display The display to take the screenshot of.
642     * @param consumer The {@link Surface} to take the screenshot into.
643     * @param width The desired width of the returned bitmap; the raw
644     * screen will be scaled down to this size.
645     * @param height The desired height of the returned bitmap; the raw
646     * screen will be scaled down to this size.
647     * @param minLayer The lowest (bottom-most Z order) surface layer to
648     * include in the screenshot.
649     * @param maxLayer The highest (top-most Z order) surface layer to
650     * include in the screenshot.
651     * @param useIdentityTransform Replace whatever transformation (rotation,
652     * scaling, translation) the surface layers are currently using with the
653     * identity transformation while taking the screenshot.
654     */
655    public static void screenshot(IBinder display, Surface consumer,
656            int width, int height, int minLayer, int maxLayer,
657            boolean useIdentityTransform) {
658        screenshot(display, consumer, new Rect(), width, height, minLayer, maxLayer,
659                false, useIdentityTransform);
660    }
661
662    /**
663     * Copy the current screen contents into the provided {@link Surface}
664     *
665     * @param display The display to take the screenshot of.
666     * @param consumer The {@link Surface} to take the screenshot into.
667     * @param width The desired width of the returned bitmap; the raw
668     * screen will be scaled down to this size.
669     * @param height The desired height of the returned bitmap; the raw
670     * screen will be scaled down to this size.
671     */
672    public static void screenshot(IBinder display, Surface consumer,
673            int width, int height) {
674        screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
675    }
676
677    /**
678     * Copy the current screen contents into the provided {@link Surface}
679     *
680     * @param display The display to take the screenshot of.
681     * @param consumer The {@link Surface} to take the screenshot into.
682     */
683    public static void screenshot(IBinder display, Surface consumer) {
684        screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false);
685    }
686
687    /**
688     * Copy the current screen contents into a bitmap and return it.
689     *
690     * CAVEAT: Versions of screenshot that return a {@link Bitmap} can
691     * be extremely slow; avoid use unless absolutely necessary; prefer
692     * the versions that use a {@link Surface} instead, such as
693     * {@link SurfaceControl#screenshot(IBinder, Surface)}.
694     *
695     * @param sourceCrop The portion of the screen to capture into the Bitmap;
696     * caller may pass in 'new Rect()' if no cropping is desired.
697     * @param width The desired width of the returned bitmap; the raw
698     * screen will be scaled down to this size.
699     * @param height The desired height of the returned bitmap; the raw
700     * screen will be scaled down to this size.
701     * @param minLayer The lowest (bottom-most Z order) surface layer to
702     * include in the screenshot.
703     * @param maxLayer The highest (top-most Z order) surface layer to
704     * include in the screenshot.
705     * @param useIdentityTransform Replace whatever transformation (rotation,
706     * scaling, translation) the surface layers are currently using with the
707     * identity transformation while taking the screenshot.
708     * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
709     * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
710     * screenshots in its native portrait orientation by default, so this is
711     * useful for returning screenshots that are independent of device
712     * orientation.
713     * @return Returns a Bitmap containing the screen contents, or null
714     * if an error occurs. Make sure to call Bitmap.recycle() as soon as
715     * possible, once its content is not needed anymore.
716     */
717    public static Bitmap screenshot(Rect sourceCrop, int width, int height,
718            int minLayer, int maxLayer, boolean useIdentityTransform,
719            int rotation) {
720        // TODO: should take the display as a parameter
721        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
722                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
723        return nativeScreenshot(displayToken, sourceCrop, width, height,
724                minLayer, maxLayer, false, useIdentityTransform, rotation);
725    }
726
727    /**
728     * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
729     * includes all Surfaces in the screenshot.
730     *
731     * @param width The desired width of the returned bitmap; the raw
732     * screen will be scaled down to this size.
733     * @param height The desired height of the returned bitmap; the raw
734     * screen will be scaled down to this size.
735     * @return Returns a Bitmap containing the screen contents, or null
736     * if an error occurs. Make sure to call Bitmap.recycle() as soon as
737     * possible, once its content is not needed anymore.
738     */
739    public static Bitmap screenshot(int width, int height) {
740        // TODO: should take the display as a parameter
741        IBinder displayToken = SurfaceControl.getBuiltInDisplay(
742                SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
743        return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,
744                false, Surface.ROTATION_0);
745    }
746
747    private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
748            int width, int height, int minLayer, int maxLayer, boolean allLayers,
749            boolean useIdentityTransform) {
750        if (display == null) {
751            throw new IllegalArgumentException("displayToken must not be null");
752        }
753        if (consumer == null) {
754            throw new IllegalArgumentException("consumer must not be null");
755        }
756        nativeScreenshot(display, consumer, sourceCrop, width, height,
757                minLayer, maxLayer, allLayers, useIdentityTransform);
758    }
759}
760