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