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 dalvik.system.CloseGuard;
     20 
     21 import android.content.res.CompatibilityInfo.Translator;
     22 import android.graphics.Bitmap;
     23 import android.graphics.Canvas;
     24 import android.graphics.Matrix;
     25 import android.graphics.Rect;
     26 import android.graphics.Region;
     27 import android.graphics.SurfaceTexture;
     28 import android.os.IBinder;
     29 import android.os.Parcelable;
     30 import android.os.Parcel;
     31 import android.os.SystemProperties;
     32 import android.util.Log;
     33 
     34 /**
     35  * Handle onto a raw buffer that is being managed by the screen compositor.
     36  */
     37 public class Surface implements Parcelable {
     38     private static final String TAG = "Surface";
     39 
     40     private static final boolean HEADLESS = "1".equals(
     41         SystemProperties.get("ro.config.headless", "0"));
     42 
     43     public static final Parcelable.Creator<Surface> CREATOR =
     44             new Parcelable.Creator<Surface>() {
     45         public Surface createFromParcel(Parcel source) {
     46             try {
     47                 Surface s = new Surface();
     48                 s.readFromParcel(source);
     49                 return s;
     50             } catch (Exception e) {
     51                 Log.e(TAG, "Exception creating surface from parcel", e);
     52                 return null;
     53             }
     54         }
     55 
     56         public Surface[] newArray(int size) {
     57             return new Surface[size];
     58         }
     59     };
     60 
     61     /**
     62      * Rotation constant: 0 degree rotation (natural orientation)
     63      */
     64     public static final int ROTATION_0 = 0;
     65 
     66     /**
     67      * Rotation constant: 90 degree rotation.
     68      */
     69     public static final int ROTATION_90 = 1;
     70 
     71     /**
     72      * Rotation constant: 180 degree rotation.
     73      */
     74     public static final int ROTATION_180 = 2;
     75 
     76     /**
     77      * Rotation constant: 270 degree rotation.
     78      */
     79     public static final int ROTATION_270 = 3;
     80 
     81     /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
     82      * these are different from the logical display ids used elsewhere in the framework */
     83 
     84     /**
     85      * Built-in physical display id: Main display.
     86      * Use only with {@link #getBuiltInDisplay()}.
     87      * @hide
     88      */
     89     public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
     90 
     91     /**
     92      * Built-in physical display id: Attached HDMI display.
     93      * Use only with {@link #getBuiltInDisplay()}.
     94      * @hide
     95      */
     96     public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
     97 
     98     /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
     99 
    100     /**
    101      * Surface creation flag: Surface is created hidden
    102      * @hide */
    103     public static final int HIDDEN = 0x00000004;
    104 
    105     /**
    106      * Surface creation flag: The surface contains secure content, special
    107      * measures will be taken to disallow the surface's content to be copied
    108      * from another process. In particular, screenshots and VNC servers will
    109      * be disabled, but other measures can take place, for instance the
    110      * surface might not be hardware accelerated.
    111      * @hide
    112      */
    113     public static final int SECURE = 0x00000080;
    114 
    115     /**
    116      * Surface creation flag: Creates a surface where color components are interpreted
    117      * as "non pre-multiplied" by their alpha channel. Of course this flag is
    118      * meaningless for surfaces without an alpha channel. By default
    119      * surfaces are pre-multiplied, which means that each color component is
    120      * already multiplied by its alpha value. In this case the blending
    121      * equation used is:
    122      *
    123      *    DEST = SRC + DEST * (1-SRC_ALPHA)
    124      *
    125      * By contrast, non pre-multiplied surfaces use the following equation:
    126      *
    127      *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
    128      *
    129      * pre-multiplied surfaces must always be used if transparent pixels are
    130      * composited on top of each-other into the surface. A pre-multiplied
    131      * surface can never lower the value of the alpha component of a given
    132      * pixel.
    133      *
    134      * In some rare situations, a non pre-multiplied surface is preferable.
    135      * @hide
    136      */
    137     public static final int NON_PREMULTIPLIED = 0x00000100;
    138 
    139     /**
    140      * Surface creation flag: Indicates that the surface must be considered opaque,
    141      * even if its pixel format is set to translucent. This can be useful if an
    142      * application needs full RGBA 8888 support for instance but will
    143      * still draw every pixel opaque.
    144      * @hide
    145      */
    146     public static final int OPAQUE = 0x00000400;
    147 
    148     /**
    149      * Surface creation flag: Application requires a hardware-protected path to an
    150      * external display sink. If a hardware-protected path is not available,
    151      * then this surface will not be displayed on the external sink.
    152      * @hide
    153      */
    154     public static final int PROTECTED_APP = 0x00000800;
    155 
    156     // 0x1000 is reserved for an independent DRM protected flag in framework
    157 
    158     /**
    159      * Surface creation flag: Creates a normal surface.
    160      * This is the default.
    161      * @hide
    162      */
    163     public static final int FX_SURFACE_NORMAL   = 0x00000000;
    164 
    165     /**
    166      * Surface creation flag: Creates a Blur surface.
    167      * Everything behind this surface is blurred by some amount.
    168      * The quality and refresh speed of the blur effect is not settable or guaranteed.
    169      * It is an error to lock a Blur surface, since it doesn't have a backing store.
    170      * @hide
    171      * @deprecated
    172      */
    173     @Deprecated
    174     public static final int FX_SURFACE_BLUR = 0x00010000;
    175 
    176     /**
    177      * Surface creation flag: Creates a Dim surface.
    178      * Everything behind this surface is dimmed by the amount specified
    179      * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
    180      * doesn't have a backing store.
    181      * @hide
    182      */
    183     public static final int FX_SURFACE_DIM = 0x00020000;
    184 
    185     /**
    186      * @hide
    187      */
    188     public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
    189 
    190     /**
    191      * Mask used for FX values above.
    192      * @hide
    193      */
    194     public static final int FX_SURFACE_MASK = 0x000F0000;
    195 
    196     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
    197 
    198     /**
    199      * Surface flag: Hide the surface.
    200      * Equivalent to calling hide().
    201      * @hide
    202      */
    203     public static final int SURFACE_HIDDEN = 0x01;
    204 
    205 
    206     private final CloseGuard mCloseGuard = CloseGuard.get();
    207     private String mName;
    208 
    209     // Note: These fields are accessed by native code.
    210     // The mSurfaceControl will only be present for Surfaces used by the window
    211     // server or system processes. When this class is parceled we defer to the
    212     // mSurfaceControl to do the parceling. Otherwise we parcel the
    213     // mNativeSurface.
    214     private int mNativeSurface; // Surface*
    215     private int mNativeSurfaceControl; // SurfaceControl*
    216     private int mGenerationId; // incremented each time mNativeSurface changes
    217     private final Canvas mCanvas = new CompatibleCanvas();
    218     private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
    219 
    220     // The Translator for density compatibility mode.  This is used for scaling
    221     // the canvas to perform the appropriate density transformation.
    222     private Translator mCompatibilityTranslator;
    223 
    224     // A matrix to scale the matrix set by application. This is set to null for
    225     // non compatibility mode.
    226     private Matrix mCompatibleMatrix;
    227 
    228     private native void nativeCreate(SurfaceSession session, String name,
    229             int w, int h, int format, int flags)
    230             throws OutOfResourcesException;
    231     private native void nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
    232             throws OutOfResourcesException;
    233     private native void nativeRelease();
    234     private native void nativeDestroy();
    235 
    236     private native boolean nativeIsValid();
    237     private native int nativeGetIdentity();
    238     private native boolean nativeIsConsumerRunningBehind();
    239 
    240     private native Canvas nativeLockCanvas(Rect dirty);
    241     private native void nativeUnlockCanvasAndPost(Canvas canvas);
    242 
    243     private static native Bitmap nativeScreenshot(IBinder displayToken,
    244             int width, int height, int minLayer, int maxLayer, boolean allLayers);
    245 
    246     private static native void nativeOpenTransaction();
    247     private static native void nativeCloseTransaction();
    248     private static native void nativeSetAnimationTransaction();
    249 
    250     private native void nativeSetLayer(int zorder);
    251     private native void nativeSetPosition(float x, float y);
    252     private native void nativeSetSize(int w, int h);
    253     private native void nativeSetTransparentRegionHint(Region region);
    254     private native void nativeSetAlpha(float alpha);
    255     private native void nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
    256     private native void nativeSetFlags(int flags, int mask);
    257     private native void nativeSetWindowCrop(Rect crop);
    258     private native void nativeSetLayerStack(int layerStack);
    259 
    260     private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
    261     private static native IBinder nativeCreateDisplay(String name, boolean secure);
    262     private static native void nativeSetDisplaySurface(
    263             IBinder displayToken, Surface surface);
    264     private static native void nativeSetDisplayLayerStack(
    265             IBinder displayToken, int layerStack);
    266     private static native void nativeSetDisplayProjection(
    267             IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect);
    268     private static native boolean nativeGetDisplayInfo(
    269             IBinder displayToken, PhysicalDisplayInfo outInfo);
    270     private static native void nativeBlankDisplay(IBinder displayToken);
    271     private static native void nativeUnblankDisplay(IBinder displayToken);
    272 
    273     private native void nativeCopyFrom(Surface other);
    274     private native void nativeTransferFrom(Surface other);
    275     private native void nativeReadFromParcel(Parcel source);
    276     private native void nativeWriteToParcel(Parcel dest);
    277 
    278 
    279     /**
    280      * Create an empty surface, which will later be filled in by readFromParcel().
    281      * @hide
    282      */
    283     public Surface() {
    284         checkHeadless();
    285 
    286         mCloseGuard.open("release");
    287     }
    288 
    289     /**
    290      * Create a surface with a name.
    291      *
    292      * The surface creation flags specify what kind of surface to create and
    293      * certain options such as whether the surface can be assumed to be opaque
    294      * and whether it should be initially hidden.  Surfaces should always be
    295      * created with the {@link #HIDDEN} flag set to ensure that they are not
    296      * made visible prematurely before all of the surface's properties have been
    297      * configured.
    298      *
    299      * Good practice is to first create the surface with the {@link #HIDDEN} flag
    300      * specified, open a transaction, set the surface layer, layer stack, alpha,
    301      * and position, call {@link #show} if appropriate, and close the transaction.
    302      *
    303      * @param session The surface session, must not be null.
    304      * @param name The surface name, must not be null.
    305      * @param w The surface initial width.
    306      * @param h The surface initial height.
    307      * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
    308      * in the creation flags.
    309      * @hide
    310      */
    311     public Surface(SurfaceSession session,
    312             String name, int w, int h, int format, int flags)
    313             throws OutOfResourcesException {
    314         if (session == null) {
    315             throw new IllegalArgumentException("session must not be null");
    316         }
    317         if (name == null) {
    318             throw new IllegalArgumentException("name must not be null");
    319         }
    320 
    321         if ((flags & HIDDEN) == 0) {
    322             Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
    323                     + "to ensure that they are not made visible prematurely before "
    324                     + "all of the surface's properties have been configured.  "
    325                     + "Set the other properties and make the surface visible within "
    326                     + "a transaction.  New surface name: " + name,
    327                     new Throwable());
    328         }
    329 
    330         checkHeadless();
    331 
    332         mName = name;
    333         nativeCreate(session, name, w, h, format, flags);
    334 
    335         mCloseGuard.open("release");
    336     }
    337 
    338     /**
    339      * Create Surface from a {@link SurfaceTexture}.
    340      *
    341      * Images drawn to the Surface will be made available to the {@link
    342      * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
    343      * SurfaceTexture#updateTexImage}.
    344      *
    345      * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
    346      * Surface.
    347      */
    348     public Surface(SurfaceTexture surfaceTexture) {
    349         if (surfaceTexture == null) {
    350             throw new IllegalArgumentException("surfaceTexture must not be null");
    351         }
    352 
    353         checkHeadless();
    354 
    355         mName = surfaceTexture.toString();
    356         try {
    357             nativeCreateFromSurfaceTexture(surfaceTexture);
    358         } catch (OutOfResourcesException ex) {
    359             // We can't throw OutOfResourcesException because it would be an API change.
    360             throw new RuntimeException(ex);
    361         }
    362 
    363         mCloseGuard.open("release");
    364     }
    365 
    366     @Override
    367     protected void finalize() throws Throwable {
    368         try {
    369             if (mCloseGuard != null) {
    370                 mCloseGuard.warnIfOpen();
    371             }
    372             nativeRelease();
    373         } finally {
    374             super.finalize();
    375         }
    376     }
    377 
    378     /**
    379      * Release the local reference to the server-side surface.
    380      * Always call release() when you're done with a Surface.
    381      * This will make the surface invalid.
    382      */
    383     public void release() {
    384         nativeRelease();
    385         mCloseGuard.close();
    386     }
    387 
    388     /**
    389      * Free all server-side state associated with this surface and
    390      * release this object's reference.  This method can only be
    391      * called from the process that created the service.
    392      * @hide
    393      */
    394     public void destroy() {
    395         nativeDestroy();
    396         mCloseGuard.close();
    397     }
    398 
    399     /**
    400      * Returns true if this object holds a valid surface.
    401      *
    402      * @return True if it holds a physical surface, so lockCanvas() will succeed.
    403      * Otherwise returns false.
    404      */
    405     public boolean isValid() {
    406         return nativeIsValid();
    407     }
    408 
    409     /**
    410      * Gets the generation number of this surface, incremented each time
    411      * the native surface contained within this object changes.
    412      *
    413      * @return The current generation number.
    414      * @hide
    415      */
    416     public int getGenerationId() {
    417         return mGenerationId;
    418     }
    419 
    420     /**
    421      * Returns true if the consumer of this Surface is running behind the producer.
    422      *
    423      * @return True if the consumer is more than one buffer ahead of the producer.
    424      * @hide
    425      */
    426     public boolean isConsumerRunningBehind() {
    427         return nativeIsConsumerRunningBehind();
    428     }
    429 
    430     /**
    431      * Gets a {@link Canvas} for drawing into this surface.
    432      *
    433      * After drawing into the provided {@link Canvas}, the caller should
    434      * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
    435      *
    436      * @param dirty A rectangle that represents the dirty region that the caller wants
    437      * to redraw.  This function may choose to expand the dirty rectangle if for example
    438      * the surface has been resized or if the previous contents of the surface were
    439      * not available.  The caller should redraw the entire dirty region as represented
    440      * by the contents of the dirty rect upon return from this function.
    441      * The caller may also pass <code>null</code> instead, in the case where the
    442      * entire surface should be redrawn.
    443      * @return A canvas for drawing into the surface.
    444      */
    445     public Canvas lockCanvas(Rect dirty)
    446             throws OutOfResourcesException, IllegalArgumentException {
    447         return nativeLockCanvas(dirty);
    448     }
    449 
    450     /**
    451      * Posts the new contents of the {@link Canvas} to the surface and
    452      * releases the {@link Canvas}.
    453      *
    454      * @param canvas The canvas previously obtained from {@link #lockCanvas}.
    455      */
    456     public void unlockCanvasAndPost(Canvas canvas) {
    457         nativeUnlockCanvasAndPost(canvas);
    458     }
    459 
    460     /**
    461      * @deprecated This API has been removed and is not supported.  Do not use.
    462      */
    463     @Deprecated
    464     public void unlockCanvas(Canvas canvas) {
    465         throw new UnsupportedOperationException();
    466     }
    467 
    468     /**
    469      * Sets the translator used to scale canvas's width/height in compatibility
    470      * mode.
    471      */
    472     void setCompatibilityTranslator(Translator translator) {
    473         if (translator != null) {
    474             float appScale = translator.applicationScale;
    475             mCompatibleMatrix = new Matrix();
    476             mCompatibleMatrix.setScale(appScale, appScale);
    477         }
    478     }
    479 
    480     /**
    481      * Like {@link #screenshot(int, int, int, int)} but includes all
    482      * Surfaces in the screenshot.
    483      *
    484      * @hide
    485      */
    486     public static Bitmap screenshot(int width, int height) {
    487         // TODO: should take the display as a parameter
    488         IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
    489         return nativeScreenshot(displayToken, width, height, 0, 0, true);
    490     }
    491 
    492     /**
    493      * Copy the current screen contents into a bitmap and return it.
    494      *
    495      * @param width The desired width of the returned bitmap; the raw
    496      * screen will be scaled down to this size.
    497      * @param height The desired height of the returned bitmap; the raw
    498      * screen will be scaled down to this size.
    499      * @param minLayer The lowest (bottom-most Z order) surface layer to
    500      * include in the screenshot.
    501      * @param maxLayer The highest (top-most Z order) surface layer to
    502      * include in the screenshot.
    503      * @return Returns a Bitmap containing the screen contents, or null
    504      * if an error occurs.
    505      *
    506      * @hide
    507      */
    508     public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
    509         // TODO: should take the display as a parameter
    510         IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
    511         return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
    512     }
    513 
    514     /*
    515      * set surface parameters.
    516      * needs to be inside open/closeTransaction block
    517      */
    518 
    519     /** start a transaction @hide */
    520     public static void openTransaction() {
    521         nativeOpenTransaction();
    522     }
    523 
    524     /** end a transaction @hide */
    525     public static void closeTransaction() {
    526         nativeCloseTransaction();
    527     }
    528 
    529     /** flag the transaction as an animation @hide */
    530     public static void setAnimationTransaction() {
    531         nativeSetAnimationTransaction();
    532     }
    533 
    534     /** @hide */
    535     public void setLayer(int zorder) {
    536         nativeSetLayer(zorder);
    537     }
    538 
    539     /** @hide */
    540     public void setPosition(int x, int y) {
    541         nativeSetPosition((float)x, (float)y);
    542     }
    543 
    544     /** @hide */
    545     public void setPosition(float x, float y) {
    546         nativeSetPosition(x, y);
    547     }
    548 
    549     /** @hide */
    550     public void setSize(int w, int h) {
    551         nativeSetSize(w, h);
    552     }
    553 
    554     /** @hide */
    555     public void hide() {
    556         nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN);
    557     }
    558 
    559     /** @hide */
    560     public void show() {
    561         nativeSetFlags(0, SURFACE_HIDDEN);
    562     }
    563 
    564     /** @hide */
    565     public void setTransparentRegionHint(Region region) {
    566         nativeSetTransparentRegionHint(region);
    567     }
    568 
    569     /** @hide */
    570     public void setAlpha(float alpha) {
    571         nativeSetAlpha(alpha);
    572     }
    573 
    574     /** @hide */
    575     public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    576         nativeSetMatrix(dsdx, dtdx, dsdy, dtdy);
    577     }
    578 
    579     /** @hide */
    580     public void setFlags(int flags, int mask) {
    581         nativeSetFlags(flags, mask);
    582     }
    583 
    584     /** @hide */
    585     public void setWindowCrop(Rect crop) {
    586         nativeSetWindowCrop(crop);
    587     }
    588 
    589     /** @hide */
    590     public void setLayerStack(int layerStack) {
    591         nativeSetLayerStack(layerStack);
    592     }
    593 
    594     /** @hide */
    595     public static IBinder getBuiltInDisplay(int builtInDisplayId) {
    596         return nativeGetBuiltInDisplay(builtInDisplayId);
    597     }
    598 
    599     /** @hide */
    600     public static IBinder createDisplay(String name, boolean secure) {
    601         if (name == null) {
    602             throw new IllegalArgumentException("name must not be null");
    603         }
    604         return nativeCreateDisplay(name, secure);
    605     }
    606 
    607     /** @hide */
    608     public static void setDisplaySurface(IBinder displayToken, Surface surface) {
    609         if (displayToken == null) {
    610             throw new IllegalArgumentException("displayToken must not be null");
    611         }
    612         nativeSetDisplaySurface(displayToken, surface);
    613     }
    614 
    615     /** @hide */
    616     public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
    617         if (displayToken == null) {
    618             throw new IllegalArgumentException("displayToken must not be null");
    619         }
    620         nativeSetDisplayLayerStack(displayToken, layerStack);
    621     }
    622 
    623     /** @hide */
    624     public static void setDisplayProjection(IBinder displayToken,
    625             int orientation, Rect layerStackRect, Rect displayRect) {
    626         if (displayToken == null) {
    627             throw new IllegalArgumentException("displayToken must not be null");
    628         }
    629         if (layerStackRect == null) {
    630             throw new IllegalArgumentException("layerStackRect must not be null");
    631         }
    632         if (displayRect == null) {
    633             throw new IllegalArgumentException("displayRect must not be null");
    634         }
    635         nativeSetDisplayProjection(displayToken, orientation, layerStackRect, displayRect);
    636     }
    637 
    638     /** @hide */
    639     public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo) {
    640         if (displayToken == null) {
    641             throw new IllegalArgumentException("displayToken must not be null");
    642         }
    643         if (outInfo == null) {
    644             throw new IllegalArgumentException("outInfo must not be null");
    645         }
    646         return nativeGetDisplayInfo(displayToken, outInfo);
    647     }
    648 
    649     /** @hide */
    650     public static void blankDisplay(IBinder displayToken) {
    651         if (displayToken == null) {
    652             throw new IllegalArgumentException("displayToken must not be null");
    653         }
    654         nativeBlankDisplay(displayToken);
    655     }
    656 
    657     /** @hide */
    658     public static void unblankDisplay(IBinder displayToken) {
    659         if (displayToken == null) {
    660             throw new IllegalArgumentException("displayToken must not be null");
    661         }
    662         nativeUnblankDisplay(displayToken);
    663     }
    664 
    665     /**
    666      * Copy another surface to this one.  This surface now holds a reference
    667      * to the same data as the original surface, and is -not- the owner.
    668      * This is for use by the window manager when returning a window surface
    669      * back from a client, converting it from the representation being managed
    670      * by the window manager to the representation the client uses to draw
    671      * in to it.
    672      * @hide
    673      */
    674     public void copyFrom(Surface other) {
    675         if (other == null) {
    676             throw new IllegalArgumentException("other must not be null");
    677         }
    678         if (other != this) {
    679             nativeCopyFrom(other);
    680         }
    681     }
    682 
    683     /**
    684      * Transfer the native state from 'other' to this surface, releasing it
    685      * from 'other'.  This is for use in the client side for drawing into a
    686      * surface; not guaranteed to work on the window manager side.
    687      * This is for use by the client to move the underlying surface from
    688      * one Surface object to another, in particular in SurfaceFlinger.
    689      * @hide.
    690      */
    691     public void transferFrom(Surface other) {
    692         if (other == null) {
    693             throw new IllegalArgumentException("other must not be null");
    694         }
    695         if (other != this) {
    696             nativeTransferFrom(other);
    697         }
    698     }
    699 
    700     @Override
    701     public int describeContents() {
    702         return 0;
    703     }
    704 
    705     public void readFromParcel(Parcel source) {
    706         if (source == null) {
    707             throw new IllegalArgumentException("source must not be null");
    708         }
    709 
    710         mName = source.readString();
    711         nativeReadFromParcel(source);
    712     }
    713 
    714     @Override
    715     public void writeToParcel(Parcel dest, int flags) {
    716         if (dest == null) {
    717             throw new IllegalArgumentException("dest must not be null");
    718         }
    719 
    720         dest.writeString(mName);
    721         nativeWriteToParcel(dest);
    722         if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
    723             release();
    724         }
    725     }
    726 
    727     @Override
    728     public String toString() {
    729         return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")";
    730     }
    731 
    732     private static void checkHeadless() {
    733         if (HEADLESS) {
    734             throw new UnsupportedOperationException("Device is headless");
    735         }
    736     }
    737 
    738     /**
    739      * Exception thrown when a surface couldn't be created or resized.
    740      */
    741     public static class OutOfResourcesException extends Exception {
    742         public OutOfResourcesException() {
    743         }
    744 
    745         public OutOfResourcesException(String name) {
    746             super(name);
    747         }
    748     }
    749 
    750     /**
    751      * Describes the properties of a physical display known to surface flinger.
    752      * @hide
    753      */
    754     public static final class PhysicalDisplayInfo {
    755         public int width;
    756         public int height;
    757         public float refreshRate;
    758         public float density;
    759         public float xDpi;
    760         public float yDpi;
    761         public boolean secure;
    762 
    763         public PhysicalDisplayInfo() {
    764         }
    765 
    766         public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
    767             copyFrom(other);
    768         }
    769 
    770         @Override
    771         public boolean equals(Object o) {
    772             return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
    773         }
    774 
    775         public boolean equals(PhysicalDisplayInfo other) {
    776             return other != null
    777                     && width == other.width
    778                     && height == other.height
    779                     && refreshRate == other.refreshRate
    780                     && density == other.density
    781                     && xDpi == other.xDpi
    782                     && yDpi == other.yDpi
    783                     && secure == other.secure;
    784         }
    785 
    786         @Override
    787         public int hashCode() {
    788             return 0; // don't care
    789         }
    790 
    791         public void copyFrom(PhysicalDisplayInfo other) {
    792             width = other.width;
    793             height = other.height;
    794             refreshRate = other.refreshRate;
    795             density = other.density;
    796             xDpi = other.xDpi;
    797             yDpi = other.yDpi;
    798             secure = other.secure;
    799         }
    800 
    801         // For debugging purposes
    802         @Override
    803         public String toString() {
    804             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
    805                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
    806                     + "}";
    807         }
    808     }
    809 
    810     /**
    811      * A Canvas class that can handle the compatibility mode.
    812      * This does two things differently.
    813      * <ul>
    814      * <li>Returns the width and height of the target metrics, rather than
    815      * native. For example, the canvas returns 320x480 even if an app is running
    816      * in WVGA high density.
    817      * <li>Scales the matrix in setMatrix by the application scale, except if
    818      * the matrix looks like obtained from getMatrix. This is a hack to handle
    819      * the case that an application uses getMatrix to keep the original matrix,
    820      * set matrix of its own, then set the original matrix back. There is no
    821      * perfect solution that works for all cases, and there are a lot of cases
    822      * that this model does not work, but we hope this works for many apps.
    823      * </ul>
    824      */
    825     private final class CompatibleCanvas extends Canvas {
    826         // A temp matrix to remember what an application obtained via {@link getMatrix}
    827         private Matrix mOrigMatrix = null;
    828 
    829         @Override
    830         public int getWidth() {
    831             int w = super.getWidth();
    832             if (mCompatibilityTranslator != null) {
    833                 w = (int)(w * mCompatibilityTranslator.applicationInvertedScale + .5f);
    834             }
    835             return w;
    836         }
    837 
    838         @Override
    839         public int getHeight() {
    840             int h = super.getHeight();
    841             if (mCompatibilityTranslator != null) {
    842                 h = (int)(h * mCompatibilityTranslator.applicationInvertedScale + .5f);
    843             }
    844             return h;
    845         }
    846 
    847         @Override
    848         public void setMatrix(Matrix matrix) {
    849             if (mCompatibleMatrix == null || mOrigMatrix == null || mOrigMatrix.equals(matrix)) {
    850                 // don't scale the matrix if it's not compatibility mode, or
    851                 // the matrix was obtained from getMatrix.
    852                 super.setMatrix(matrix);
    853             } else {
    854                 Matrix m = new Matrix(mCompatibleMatrix);
    855                 m.preConcat(matrix);
    856                 super.setMatrix(m);
    857             }
    858         }
    859 
    860         @Override
    861         public void getMatrix(Matrix m) {
    862             super.getMatrix(m);
    863             if (mOrigMatrix == null) {
    864                 mOrigMatrix = new Matrix();
    865             }
    866             mOrigMatrix.set(m);
    867         }
    868     }
    869 }
    870