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