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     * 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
475        public PhysicalDisplayInfo() {
476        }
477
478        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
479            copyFrom(other);
480        }
481
482        @Override
483        public boolean equals(Object o) {
484            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
485        }
486
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
501        public int hashCode() {
502            return 0; // don't care
503        }
504
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
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
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
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
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
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
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
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
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
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
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
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
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     */
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     */
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     */
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     */
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     */
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
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