Surface.java revision fa25bf5382467b1018bd9af7f1cb30a23d7d59f7
1/*
2 * Copyright (C) 2007 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 android.content.res.CompatibilityInfo.Translator;
20import android.graphics.*;
21import android.os.Parcelable;
22import android.os.Parcel;
23import android.os.SystemProperties;
24import android.util.Log;
25
26/**
27 * Handle onto a raw buffer that is being managed by the screen compositor.
28 */
29public class Surface implements Parcelable {
30    private static final String LOG_TAG = "Surface";
31    private static final boolean DEBUG_RELEASE = false;
32
33    /* orientations for setOrientation() */
34    public static final int ROTATION_0       = 0;
35    public static final int ROTATION_90      = 1;
36    public static final int ROTATION_180     = 2;
37    public static final int ROTATION_270     = 3;
38
39    private static final boolean headless = "1".equals(
40        SystemProperties.get("ro.config.headless", "0"));
41
42    private static void checkHeadless() {
43        if(headless) {
44            throw new UnsupportedOperationException("Device is headless");
45        }
46    }
47
48    /**
49     * Create Surface from a {@link SurfaceTexture}.
50     *
51     * Images drawn to the Surface will be made available to the {@link
52     * SurfaceTexture}, which can attach them an OpenGL ES texture via {@link
53     * SurfaceTexture#updateTexImage}.
54     *
55     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
56     * Surface.
57     */
58    public Surface(SurfaceTexture surfaceTexture) {
59        checkHeadless();
60
61        if (DEBUG_RELEASE) {
62            mCreationStack = new Exception();
63        }
64        mCanvas = new CompatibleCanvas();
65        initFromSurfaceTexture(surfaceTexture);
66    }
67
68    /**
69     * Does this object hold a valid surface?  Returns true if it holds
70     * a physical surface, so lockCanvas() will succeed.  Otherwise
71     * returns false.
72     */
73    public native   boolean isValid();
74
75    /** Release the local reference to the server-side surface.
76     * Always call release() when you're done with a Surface. This will
77     * make the surface invalid.
78     */
79    public native void release();
80
81    /** draw into a surface */
82    public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException {
83        /*
84         * the dirty rectangle may be expanded to the surface's size, if for
85         * instance it has been resized or if the bits were lost, since the last
86         * call.
87         */
88        return lockCanvasNative(dirty);
89    }
90
91    /** unlock the surface and asks a page flip */
92    public native   void unlockCanvasAndPost(Canvas canvas);
93
94    /**
95     * unlock the surface. the screen won't be updated until
96     * post() or postAll() is called
97     */
98    public native   void unlockCanvas(Canvas canvas);
99
100    @Override
101    public String toString() {
102        return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
103    }
104
105    public int describeContents() {
106        return 0;
107    }
108
109    public native   void readFromParcel(Parcel source);
110    public native   void writeToParcel(Parcel dest, int flags);
111
112    /**
113     * Exception thrown when a surface couldn't be created or resized
114     */
115    public static class OutOfResourcesException extends Exception {
116        public OutOfResourcesException() {
117        }
118        public OutOfResourcesException(String name) {
119            super(name);
120        }
121    }
122
123    /*
124     * -----------------------------------------------------------------------
125     * No user serviceable parts beyond this point
126     * -----------------------------------------------------------------------
127     */
128
129    /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
130
131    /** Surface is created hidden @hide */
132    public static final int HIDDEN              = 0x00000004;
133
134    /** The surface contains secure content, special measures will
135     * be taken to disallow the surface's content to be copied from
136     * another process. In particular, screenshots and VNC servers will
137     * be disabled, but other measures can take place, for instance the
138     * surface might not be hardware accelerated.
139     * @hide*/
140    public static final int SECURE              = 0x00000080;
141
142    /** Creates a surface where color components are interpreted as
143     *  "non pre-multiplied" by their alpha channel. Of course this flag is
144     *  meaningless for surfaces without an alpha channel. By default
145     *  surfaces are pre-multiplied, which means that each color component is
146     *  already multiplied by its alpha value. In this case the blending
147     *  equation used is:
148     *
149     *    DEST = SRC + DEST * (1-SRC_ALPHA)
150     *
151     *  By contrast, non pre-multiplied surfaces use the following equation:
152     *
153     *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
154     *
155     *  pre-multiplied surfaces must always be used if transparent pixels are
156     *  composited on top of each-other into the surface. A pre-multiplied
157     *  surface can never lower the value of the alpha component of a given
158     *  pixel.
159     *
160     *  In some rare situations, a non pre-multiplied surface is preferable.
161     *
162     *  @hide
163     */
164    public static final int NON_PREMULTIPLIED   = 0x00000100;
165
166    /**
167     * Indicates that the surface must be considered opaque, even if its
168     * pixel format is set to translucent. This can be useful if an
169     * application needs full RGBA 8888 support for instance but will
170     * still draw every pixel opaque.
171     *
172     * @hide
173     */
174    public static final int OPAQUE              = 0x00000400;
175
176    /**
177     * Application requires a hardware-protected path to an
178     * external display sink. If a hardware-protected path is not available,
179     * then this surface will not be displayed on the external sink.
180     *
181     * @hide
182     */
183    public static final int PROTECTED_APP       = 0x00000800;
184
185    // 0x1000 is reserved for an independent DRM protected flag in framework
186
187    /** Creates a normal surface. This is the default. @hide */
188    public static final int FX_SURFACE_NORMAL   = 0x00000000;
189
190    /** Creates a Blur surface. Everything behind this surface is blurred
191     * by some amount. The quality and refresh speed of the blur effect
192     * is not settable or guaranteed.
193     * It is an error to lock a Blur surface, since it doesn't have
194     * a backing store.
195     * @hide
196     * @deprecated
197     */
198    @Deprecated
199    public static final int FX_SURFACE_BLUR     = 0x00010000;
200
201    /** Creates a Dim surface. Everything behind this surface is dimmed
202     * by the amount specified in {@link #setAlpha}.
203     * It is an error to lock a Dim surface, since it doesn't have
204     * a backing store.
205     * @hide
206     */
207    public static final int FX_SURFACE_DIM     = 0x00020000;
208
209    /** @hide */
210    public static final int FX_SURFACE_SCREENSHOT   = 0x00030000;
211
212    /** Mask used for FX values above @hide */
213    public static final int FX_SURFACE_MASK     = 0x000F0000;
214
215    /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
216
217    /** Hide the surface. Equivalent to calling hide(). @hide */
218    public static final int SURFACE_HIDDEN    = 0x01;
219
220    // The mSurfaceControl will only be present for Surfaces used by the window
221    // server or system processes. When this class is parceled we defer to the
222    // mSurfaceControl to do the parceling. Otherwise we parcel the
223    // mNativeSurface.
224    private int mSurfaceControl;
225    private int mSaveCount;
226    private Canvas mCanvas;
227    private int mNativeSurface;
228    private int mSurfaceGenerationId;
229    private String mName;
230
231    // The Translator for density compatibility mode.  This is used for scaling
232    // the canvas to perform the appropriate density transformation.
233    private Translator mCompatibilityTranslator;
234
235    // A matrix to scale the matrix set by application. This is set to null for
236    // non compatibility mode.
237    private Matrix mCompatibleMatrix;
238
239    private Exception mCreationStack;
240
241
242    /*
243     * We use a class initializer to allow the native code to cache some
244     * field offsets.
245     */
246    native private static void nativeClassInit();
247    static { nativeClassInit(); }
248
249    /** create a surface @hide */
250    public Surface(SurfaceSession s,
251            int pid, int display, int w, int h, int format, int flags)
252        throws OutOfResourcesException {
253        checkHeadless();
254
255        if (DEBUG_RELEASE) {
256            mCreationStack = new Exception();
257        }
258        mCanvas = new CompatibleCanvas();
259        init(s,pid,null,display,w,h,format,flags);
260    }
261
262    /** create a surface with a name @hide */
263    public Surface(SurfaceSession s,
264            int pid, String name, int display, int w, int h, int format, int flags)
265        throws OutOfResourcesException {
266        checkHeadless();
267
268        if (DEBUG_RELEASE) {
269            mCreationStack = new Exception();
270        }
271        mCanvas = new CompatibleCanvas();
272        init(s,pid,name,display,w,h,format,flags);
273        mName = name;
274    }
275
276    /**
277     * Create an empty surface, which will later be filled in by
278     * readFromParcel().
279     * @hide
280     */
281    public Surface() {
282        checkHeadless();
283
284        if (DEBUG_RELEASE) {
285            mCreationStack = new Exception();
286        }
287        mCanvas = new CompatibleCanvas();
288    }
289
290    private Surface(Parcel source) throws OutOfResourcesException {
291        init(source);
292    }
293
294    /**
295     * Copy another surface to this one.  This surface now holds a reference
296     * to the same data as the original surface, and is -not- the owner.
297     * This is for use by the window manager when returning a window surface
298     * back from a client, converting it from the representation being managed
299     * by the window manager to the representation the client uses to draw
300     * in to it.
301     * @hide
302     */
303    public native void copyFrom(Surface o);
304
305    /**
306     * Transfer the native state from 'o' to this surface, releasing it
307     * from 'o'.  This is for use in the client side for drawing into a
308     * surface; not guaranteed to work on the window manager side.
309     * This is for use by the client to move the underlying surface from
310     * one Surface object to another, in particular in SurfaceFlinger.
311     * @hide.
312     */
313    public native void transferFrom(Surface o);
314
315    /** @hide */
316    public int getGenerationId() {
317        return mSurfaceGenerationId;
318    }
319
320
321    /**
322     * Whether the consumer of this Surface is running behind the producer;
323     * that is, isConsumerRunningBehind() returns true if the consumer is more
324     * than one buffer ahead of the producer.
325     * @hide
326     */
327    public native boolean isConsumerRunningBehind();
328
329    /**
330     * A Canvas class that can handle the compatibility mode. This does two
331     * things differently.
332     * <ul>
333     * <li>Returns the width and height of the target metrics, rather than
334     * native. For example, the canvas returns 320x480 even if an app is running
335     * in WVGA high density.
336     * <li>Scales the matrix in setMatrix by the application scale, except if
337     * the matrix looks like obtained from getMatrix. This is a hack to handle
338     * the case that an application uses getMatrix to keep the original matrix,
339     * set matrix of its own, then set the original matrix back. There is no
340     * perfect solution that works for all cases, and there are a lot of cases
341     * that this model does not work, but we hope this works for many apps.
342     * </ul>
343     */
344    private class CompatibleCanvas extends Canvas {
345        // A temp matrix to remember what an application obtained via {@link getMatrix}
346        private Matrix mOrigMatrix = null;
347
348        @Override
349        public int getWidth() {
350            int w = super.getWidth();
351            if (mCompatibilityTranslator != null) {
352                w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f);
353            }
354            return w;
355        }
356
357        @Override
358        public int getHeight() {
359            int h = super.getHeight();
360            if (mCompatibilityTranslator != null) {
361                h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f);
362            }
363            return h;
364        }
365
366        @Override
367        public void setMatrix(Matrix matrix) {
368            if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
369                // don't scale the matrix if it's not compatibility mode, or
370                // the matrix was obtained from getMatrix.
371                super.setMatrix(matrix);
372            } else {
373                Matrix m = new Matrix(mCompatibleMatrix);
374                m.preConcat(matrix);
375                super.setMatrix(m);
376            }
377        }
378
379        @Override
380        public void getMatrix(Matrix m) {
381            super.getMatrix(m);
382            if (mOrigMatrix == null) {
383                mOrigMatrix = new Matrix();
384            }
385            mOrigMatrix.set(m);
386        }
387    }
388
389    /**
390     * Sets the translator used to scale canvas's width/height in compatibility
391     * mode.
392     */
393    void setCompatibilityTranslator(Translator translator) {
394        if (translator != null) {
395            float appScale = translator.applicationScale;
396            mCompatibleMatrix = new Matrix();
397            mCompatibleMatrix.setScale(appScale, appScale);
398        }
399    }
400
401    /** Free all server-side state associated with this surface and
402     * release this object's reference. @hide */
403    public native void destroy();
404
405    private native Canvas lockCanvasNative(Rect dirty);
406
407    /**
408     * set the orientation of the given display.
409     * @param display
410     * @param orientation
411     * @hide
412     */
413    public static native void setOrientation(int display, int orientation);
414
415    /**
416     * Like {@link #screenshot(int, int, int, int)} but includes all
417     * Surfaces in the screenshot.
418     *
419     * @hide
420     */
421    public static native Bitmap screenshot(int width, int height);
422
423    /**
424     * Copy the current screen contents into a bitmap and return it.
425     *
426     * @param width The desired width of the returned bitmap; the raw
427     * screen will be scaled down to this size.
428     * @param height The desired height of the returned bitmap; the raw
429     * screen will be scaled down to this size.
430     * @param minLayer The lowest (bottom-most Z order) surface layer to
431     * include in the screenshot.
432     * @param maxLayer The highest (top-most Z order) surface layer to
433     * include in the screenshot.
434     * @return Returns a Bitmap containing the screen contents.
435     *
436     * @hide
437     */
438    public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
439
440
441    /*
442     * set surface parameters.
443     * needs to be inside open/closeTransaction block
444     */
445
446    /** start a transaction @hide */
447    public static native   void openTransaction();
448    /** end a transaction @hide */
449    public static native   void closeTransaction();
450    /** @hide */
451    public native   void setLayer(int zorder);
452    /** @hide */
453    public void setPosition(int x, int y) { setPosition((float)x, (float)y); }
454    /** @hide */
455    public native   void setPosition(float x, float y);
456    /** @hide */
457    public native   void setSize(int w, int h);
458    /** @hide */
459    public native   void hide();
460    /** @hide */
461    public native   void show();
462    /** @hide */
463    public native   void setTransparentRegionHint(Region region);
464    /** @hide */
465    public native   void setAlpha(float alpha);
466    /** @hide */
467    public native   void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
468    /** @hide */
469    public native   void setFlags(int flags, int mask);
470    /** @hide */
471    public native   void setWindowCrop(Rect crop);
472
473
474
475    public static final Parcelable.Creator<Surface> CREATOR
476            = new Parcelable.Creator<Surface>()
477    {
478        public Surface createFromParcel(Parcel source) {
479            try {
480                return new Surface(source);
481            } catch (Exception e) {
482                Log.e(LOG_TAG, "Exception creating surface from parcel", e);
483            }
484            return null;
485        }
486
487        public Surface[] newArray(int size) {
488            return new Surface[size];
489        }
490    };
491
492    @Override
493    protected void finalize() throws Throwable {
494        try {
495            super.finalize();
496        } finally {
497            if (mNativeSurface != 0 || mSurfaceControl != 0) {
498                if (DEBUG_RELEASE) {
499                    Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() ("
500                            + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack);
501                } else {
502                    Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() ("
503                            + mNativeSurface + ", " + mSurfaceControl + ")");
504                }
505            }
506            release();
507        }
508    }
509
510    private native void init(SurfaceSession s,
511            int pid, String name, int display, int w, int h, int format, int flags)
512            throws OutOfResourcesException;
513
514    private native void init(Parcel source);
515
516    private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
517
518    private native int getIdentity();
519}
520