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