Home | History | Annotate | Download | only in view
      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 
     17 package android.view;
     18 
     19 import android.content.res.CompatibilityInfo.Translator;
     20 import android.graphics.*;
     21 import android.os.Parcelable;
     22 import android.os.Parcel;
     23 import android.os.SystemProperties;
     24 import android.util.Log;
     25 
     26 /**
     27  * Handle onto a raw buffer that is being managed by the screen compositor.
     28  */
     29 public 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     /** Freeze the surface. Equivalent to calling freeze(). @hide */
    221     public static final int SURFACE_FROZEN     = 0x02;
    222 
    223     /** Enable dithering when compositing this surface @hide */
    224     public static final int SURFACE_DITHER    = 0x04;
    225 
    226     // The mSurfaceControl will only be present for Surfaces used by the window
    227     // server or system processes. When this class is parceled we defer to the
    228     // mSurfaceControl to do the parceling. Otherwise we parcel the
    229     // mNativeSurface.
    230     private int mSurfaceControl;
    231     private int mSaveCount;
    232     private Canvas mCanvas;
    233     private int mNativeSurface;
    234     private int mSurfaceGenerationId;
    235     private String mName;
    236 
    237     // The Translator for density compatibility mode.  This is used for scaling
    238     // the canvas to perform the appropriate density transformation.
    239     private Translator mCompatibilityTranslator;
    240 
    241     // A matrix to scale the matrix set by application. This is set to null for
    242     // non compatibility mode.
    243     private Matrix mCompatibleMatrix;
    244 
    245     private Exception mCreationStack;
    246 
    247 
    248     /*
    249      * We use a class initializer to allow the native code to cache some
    250      * field offsets.
    251      */
    252     native private static void nativeClassInit();
    253     static { nativeClassInit(); }
    254 
    255     /** create a surface @hide */
    256     public Surface(SurfaceSession s,
    257             int pid, int display, int w, int h, int format, int flags)
    258         throws OutOfResourcesException {
    259         checkHeadless();
    260 
    261         if (DEBUG_RELEASE) {
    262             mCreationStack = new Exception();
    263         }
    264         mCanvas = new CompatibleCanvas();
    265         init(s,pid,null,display,w,h,format,flags);
    266     }
    267 
    268     /** create a surface with a name @hide */
    269     public Surface(SurfaceSession s,
    270             int pid, String name, int display, int w, int h, int format, int flags)
    271         throws OutOfResourcesException {
    272         checkHeadless();
    273 
    274         if (DEBUG_RELEASE) {
    275             mCreationStack = new Exception();
    276         }
    277         mCanvas = new CompatibleCanvas();
    278         init(s,pid,name,display,w,h,format,flags);
    279         mName = name;
    280     }
    281 
    282     /**
    283      * Create an empty surface, which will later be filled in by
    284      * readFromParcel().
    285      * @hide
    286      */
    287     public Surface() {
    288         checkHeadless();
    289 
    290         if (DEBUG_RELEASE) {
    291             mCreationStack = new Exception();
    292         }
    293         mCanvas = new CompatibleCanvas();
    294     }
    295 
    296     private Surface(Parcel source) throws OutOfResourcesException {
    297         init(source);
    298     }
    299 
    300     /**
    301      * Copy another surface to this one.  This surface now holds a reference
    302      * to the same data as the original surface, and is -not- the owner.
    303      * This is for use by the window manager when returning a window surface
    304      * back from a client, converting it from the representation being managed
    305      * by the window manager to the representation the client uses to draw
    306      * in to it.
    307      * @hide
    308      */
    309     public native void copyFrom(Surface o);
    310 
    311     /**
    312      * Transfer the native state from 'o' to this surface, releasing it
    313      * from 'o'.  This is for use in the client side for drawing into a
    314      * surface; not guaranteed to work on the window manager side.
    315      * This is for use by the client to move the underlying surface from
    316      * one Surface object to another, in particular in SurfaceFlinger.
    317      * @hide.
    318      */
    319     public native void transferFrom(Surface o);
    320 
    321     /** @hide */
    322     public int getGenerationId() {
    323         return mSurfaceGenerationId;
    324     }
    325 
    326 
    327     /**
    328      * Whether the consumer of this Surface is running behind the producer;
    329      * that is, isConsumerRunningBehind() returns true if the consumer is more
    330      * than one buffer ahead of the producer.
    331      * @hide
    332      */
    333     public native boolean isConsumerRunningBehind();
    334 
    335     /**
    336      * A Canvas class that can handle the compatibility mode. This does two
    337      * things differently.
    338      * <ul>
    339      * <li>Returns the width and height of the target metrics, rather than
    340      * native. For example, the canvas returns 320x480 even if an app is running
    341      * in WVGA high density.
    342      * <li>Scales the matrix in setMatrix by the application scale, except if
    343      * the matrix looks like obtained from getMatrix. This is a hack to handle
    344      * the case that an application uses getMatrix to keep the original matrix,
    345      * set matrix of its own, then set the original matrix back. There is no
    346      * perfect solution that works for all cases, and there are a lot of cases
    347      * that this model does not work, but we hope this works for many apps.
    348      * </ul>
    349      */
    350     private class CompatibleCanvas extends Canvas {
    351         // A temp matrix to remember what an application obtained via {@link getMatrix}
    352         private Matrix mOrigMatrix = null;
    353 
    354         @Override
    355         public int getWidth() {
    356             int w = super.getWidth();
    357             if (mCompatibilityTranslator != null) {
    358                 w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f);
    359             }
    360             return w;
    361         }
    362 
    363         @Override
    364         public int getHeight() {
    365             int h = super.getHeight();
    366             if (mCompatibilityTranslator != null) {
    367                 h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f);
    368             }
    369             return h;
    370         }
    371 
    372         @Override
    373         public void setMatrix(Matrix matrix) {
    374             if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
    375                 // don't scale the matrix if it's not compatibility mode, or
    376                 // the matrix was obtained from getMatrix.
    377                 super.setMatrix(matrix);
    378             } else {
    379                 Matrix m = new Matrix(mCompatibleMatrix);
    380                 m.preConcat(matrix);
    381                 super.setMatrix(m);
    382             }
    383         }
    384 
    385         @Override
    386         public void getMatrix(Matrix m) {
    387             super.getMatrix(m);
    388             if (mOrigMatrix == null) {
    389                 mOrigMatrix = new Matrix();
    390             }
    391             mOrigMatrix.set(m);
    392         }
    393     }
    394 
    395     /**
    396      * Sets the translator used to scale canvas's width/height in compatibility
    397      * mode.
    398      */
    399     void setCompatibilityTranslator(Translator translator) {
    400         if (translator != null) {
    401             float appScale = translator.applicationScale;
    402             mCompatibleMatrix = new Matrix();
    403             mCompatibleMatrix.setScale(appScale, appScale);
    404         }
    405     }
    406 
    407     /** Free all server-side state associated with this surface and
    408      * release this object's reference. @hide */
    409     public native void destroy();
    410 
    411     private native Canvas lockCanvasNative(Rect dirty);
    412 
    413     /*
    414      * set display parameters & screenshots
    415      */
    416 
    417     /**
    418      * Freezes the specified display, No updating of the screen will occur
    419      * until unfreezeDisplay() is called. Everything else works as usual though,
    420      * in particular transactions.
    421      * @param display
    422      * @hide
    423      */
    424     public static native   void freezeDisplay(int display);
    425 
    426     /**
    427      * resume updating the specified display.
    428      * @param display
    429      * @hide
    430      */
    431     public static native   void unfreezeDisplay(int display);
    432 
    433     /**
    434      * set the orientation of the given display.
    435      * @param display
    436      * @param orientation
    437      * @param flags Currently unused, set to 0.
    438      * @hide
    439      */
    440     public static native   void setOrientation(int display, int orientation, int flags);
    441 
    442     /**
    443      * set the orientation of the given display.
    444      * @param display
    445      * @param orientation
    446      * @hide
    447      */
    448     public static void setOrientation(int display, int orientation) {
    449         setOrientation(display, orientation, 0);
    450     }
    451 
    452     /**
    453      * Like {@link #screenshot(int, int, int, int)} but includes all
    454      * Surfaces in the screenshot.
    455      *
    456      * @hide
    457      */
    458     public static native Bitmap screenshot(int width, int height);
    459 
    460     /**
    461      * Copy the current screen contents into a bitmap and return it.
    462      *
    463      * @param width The desired width of the returned bitmap; the raw
    464      * screen will be scaled down to this size.
    465      * @param height The desired height of the returned bitmap; the raw
    466      * screen will be scaled down to this size.
    467      * @param minLayer The lowest (bottom-most Z order) surface layer to
    468      * include in the screenshot.
    469      * @param maxLayer The highest (top-most Z order) surface layer to
    470      * include in the screenshot.
    471      * @return Returns a Bitmap containing the screen contents.
    472      *
    473      * @hide
    474      */
    475     public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
    476 
    477 
    478     /*
    479      * set surface parameters.
    480      * needs to be inside open/closeTransaction block
    481      */
    482 
    483     /** start a transaction @hide */
    484     public static native   void openTransaction();
    485     /** end a transaction @hide */
    486     public static native   void closeTransaction();
    487     /** @hide */
    488     public native   void setLayer(int zorder);
    489     /** @hide */
    490     public void setPosition(int x, int y) { setPosition((float)x, (float)y); }
    491     /** @hide */
    492     public native   void setPosition(float x, float y);
    493     /** @hide */
    494     public native   void setSize(int w, int h);
    495     /** @hide */
    496     public native   void hide();
    497     /** @hide */
    498     public native   void show();
    499     /** @hide */
    500     public native   void setTransparentRegionHint(Region region);
    501     /** @hide */
    502     public native   void setAlpha(float alpha);
    503     /** @hide */
    504     public native   void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
    505     /** @hide */
    506     public native   void freeze();
    507     /** @hide */
    508     public native   void unfreeze();
    509     /** @hide */
    510     public native   void setFreezeTint(int tint);
    511     /** @hide */
    512     public native   void setFlags(int flags, int mask);
    513     /** @hide */
    514     public native   void setWindowCrop(Rect crop);
    515 
    516 
    517 
    518     public static final Parcelable.Creator<Surface> CREATOR
    519             = new Parcelable.Creator<Surface>()
    520     {
    521         public Surface createFromParcel(Parcel source) {
    522             try {
    523                 return new Surface(source);
    524             } catch (Exception e) {
    525                 Log.e(LOG_TAG, "Exception creating surface from parcel", e);
    526             }
    527             return null;
    528         }
    529 
    530         public Surface[] newArray(int size) {
    531             return new Surface[size];
    532         }
    533     };
    534 
    535     @Override
    536     protected void finalize() throws Throwable {
    537         try {
    538             super.finalize();
    539         } finally {
    540             if (mNativeSurface != 0 || mSurfaceControl != 0) {
    541                 if (DEBUG_RELEASE) {
    542                     Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() ("
    543                             + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack);
    544                 } else {
    545                     Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() ("
    546                             + mNativeSurface + ", " + mSurfaceControl + ")");
    547                 }
    548             }
    549             release();
    550         }
    551     }
    552 
    553     private native void init(SurfaceSession s,
    554             int pid, String name, int display, int w, int h, int format, int flags)
    555             throws OutOfResourcesException;
    556 
    557     private native void init(Parcel source);
    558 
    559     private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
    560 
    561     private native int getIdentity();
    562 }
    563