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