Home | History | Annotate | Download | only in view
      1 /*
      2  * Copyright (C) 2013 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 import android.graphics.Bitmap;
     21 import android.graphics.Rect;
     22 import android.graphics.Region;
     23 import android.view.Surface;
     24 import android.os.IBinder;
     25 import android.os.SystemProperties;
     26 import android.util.Log;
     27 import android.view.Surface.OutOfResourcesException;
     28 
     29 /**
     30  * SurfaceControl
     31  *  @hide
     32  */
     33 public class SurfaceControl {
     34     private static final String TAG = "SurfaceControl";
     35 
     36     private static native int nativeCreate(SurfaceSession session, String name,
     37             int w, int h, int format, int flags)
     38             throws OutOfResourcesException;
     39     private static native void nativeRelease(int nativeObject);
     40     private static native void nativeDestroy(int nativeObject);
     41 
     42     private static native Bitmap nativeScreenshot(IBinder displayToken,
     43             int width, int height, int minLayer, int maxLayer, boolean allLayers);
     44     private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
     45             int width, int height, int minLayer, int maxLayer, boolean allLayers);
     46 
     47     private static native void nativeOpenTransaction();
     48     private static native void nativeCloseTransaction();
     49     private static native void nativeSetAnimationTransaction();
     50 
     51     private static native void nativeSetLayer(int nativeObject, int zorder);
     52     private static native void nativeSetPosition(int nativeObject, float x, float y);
     53     private static native void nativeSetSize(int nativeObject, int w, int h);
     54     private static native void nativeSetTransparentRegionHint(int nativeObject, Region region);
     55     private static native void nativeSetAlpha(int nativeObject, float alpha);
     56     private static native void nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
     57     private static native void nativeSetFlags(int nativeObject, int flags, int mask);
     58     private static native void nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b);
     59     private static native void nativeSetLayerStack(int nativeObject, int layerStack);
     60 
     61     private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
     62     private static native IBinder nativeCreateDisplay(String name, boolean secure);
     63     private static native void nativeDestroyDisplay(IBinder displayToken);
     64     private static native void nativeSetDisplaySurface(
     65             IBinder displayToken, int nativeSurfaceObject);
     66     private static native void nativeSetDisplayLayerStack(
     67             IBinder displayToken, int layerStack);
     68     private static native void nativeSetDisplayProjection(
     69             IBinder displayToken, int orientation,
     70             int l, int t, int r, int b,
     71             int L, int T, int R, int B);
     72     private static native boolean nativeGetDisplayInfo(
     73             IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
     74     private static native void nativeBlankDisplay(IBinder displayToken);
     75     private static native void nativeUnblankDisplay(IBinder displayToken);
     76 
     77 
     78     private final CloseGuard mCloseGuard = CloseGuard.get();
     79     private final String mName;
     80     int mNativeObject; // package visibility only for Surface.java access
     81 
     82     private static final boolean HEADLESS = "1".equals(
     83         SystemProperties.get("ro.config.headless", "0"));
     84 
     85     /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
     86 
     87     /**
     88      * Surface creation flag: Surface is created hidden
     89      */
     90     public static final int HIDDEN = 0x00000004;
     91 
     92     /**
     93      * Surface creation flag: The surface contains secure content, special
     94      * measures will be taken to disallow the surface's content to be copied
     95      * from another process. In particular, screenshots and VNC servers will
     96      * be disabled, but other measures can take place, for instance the
     97      * surface might not be hardware accelerated.
     98      *
     99      */
    100     public static final int SECURE = 0x00000080;
    101 
    102     /**
    103      * Surface creation flag: Creates a surface where color components are interpreted
    104      * as "non pre-multiplied" by their alpha channel. Of course this flag is
    105      * meaningless for surfaces without an alpha channel. By default
    106      * surfaces are pre-multiplied, which means that each color component is
    107      * already multiplied by its alpha value. In this case the blending
    108      * equation used is:
    109      *
    110      *    DEST = SRC + DEST * (1-SRC_ALPHA)
    111      *
    112      * By contrast, non pre-multiplied surfaces use the following equation:
    113      *
    114      *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
    115      *
    116      * pre-multiplied surfaces must always be used if transparent pixels are
    117      * composited on top of each-other into the surface. A pre-multiplied
    118      * surface can never lower the value of the alpha component of a given
    119      * pixel.
    120      *
    121      * In some rare situations, a non pre-multiplied surface is preferable.
    122      *
    123      */
    124     public static final int NON_PREMULTIPLIED = 0x00000100;
    125 
    126     /**
    127      * Surface creation flag: Indicates that the surface must be considered opaque,
    128      * even if its pixel format is set to translucent. This can be useful if an
    129      * application needs full RGBA 8888 support for instance but will
    130      * still draw every pixel opaque.
    131      *
    132      */
    133     public static final int OPAQUE = 0x00000400;
    134 
    135     /**
    136      * Surface creation flag: Application requires a hardware-protected path to an
    137      * external display sink. If a hardware-protected path is not available,
    138      * then this surface will not be displayed on the external sink.
    139      *
    140      */
    141     public static final int PROTECTED_APP = 0x00000800;
    142 
    143     // 0x1000 is reserved for an independent DRM protected flag in framework
    144 
    145     /**
    146      * Surface creation flag: Creates a normal surface.
    147      * This is the default.
    148      *
    149      */
    150     public static final int FX_SURFACE_NORMAL   = 0x00000000;
    151 
    152     /**
    153      * Surface creation flag: Creates a Dim surface.
    154      * Everything behind this surface is dimmed by the amount specified
    155      * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
    156      * doesn't have a backing store.
    157      *
    158      */
    159     public static final int FX_SURFACE_DIM = 0x00020000;
    160 
    161     /**
    162      * Mask used for FX values above.
    163      *
    164      */
    165     public static final int FX_SURFACE_MASK = 0x000F0000;
    166 
    167     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
    168 
    169     /**
    170      * Surface flag: Hide the surface.
    171      * Equivalent to calling hide().
    172      */
    173     public static final int SURFACE_HIDDEN = 0x01;
    174 
    175 
    176     /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
    177      * these are different from the logical display ids used elsewhere in the framework */
    178 
    179     /**
    180      * Built-in physical display id: Main display.
    181      * Use only with {@link SurfaceControl#getBuiltInDisplay()}.
    182      */
    183     public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
    184 
    185     /**
    186      * Built-in physical display id: Attached HDMI display.
    187      * Use only with {@link SurfaceControl#getBuiltInDisplay()}.
    188      */
    189     public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
    190 
    191 
    192 
    193     /**
    194      * Create a surface with a name.
    195      *
    196      * The surface creation flags specify what kind of surface to create and
    197      * certain options such as whether the surface can be assumed to be opaque
    198      * and whether it should be initially hidden.  Surfaces should always be
    199      * created with the {@link #HIDDEN} flag set to ensure that they are not
    200      * made visible prematurely before all of the surface's properties have been
    201      * configured.
    202      *
    203      * Good practice is to first create the surface with the {@link #HIDDEN} flag
    204      * specified, open a transaction, set the surface layer, layer stack, alpha,
    205      * and position, call {@link #show} if appropriate, and close the transaction.
    206      *
    207      * @param session The surface session, must not be null.
    208      * @param name The surface name, must not be null.
    209      * @param w The surface initial width.
    210      * @param h The surface initial height.
    211      * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
    212      * in the creation flags.
    213      *
    214      * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
    215      */
    216     public SurfaceControl(SurfaceSession session,
    217             String name, int w, int h, int format, int flags)
    218                     throws OutOfResourcesException {
    219         if (session == null) {
    220             throw new IllegalArgumentException("session must not be null");
    221         }
    222         if (name == null) {
    223             throw new IllegalArgumentException("name must not be null");
    224         }
    225 
    226         if ((flags & SurfaceControl.HIDDEN) == 0) {
    227             Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
    228                     + "to ensure that they are not made visible prematurely before "
    229                     + "all of the surface's properties have been configured.  "
    230                     + "Set the other properties and make the surface visible within "
    231                     + "a transaction.  New surface name: " + name,
    232                     new Throwable());
    233         }
    234 
    235         checkHeadless();
    236 
    237         mName = name;
    238         mNativeObject = nativeCreate(session, name, w, h, format, flags);
    239         if (mNativeObject == 0) {
    240             throw new OutOfResourcesException(
    241                     "Couldn't allocate SurfaceControl native object");
    242         }
    243 
    244         mCloseGuard.open("release");
    245     }
    246 
    247     @Override
    248     protected void finalize() throws Throwable {
    249         try {
    250             if (mCloseGuard != null) {
    251                 mCloseGuard.warnIfOpen();
    252             }
    253             if (mNativeObject != 0) {
    254                 nativeRelease(mNativeObject);
    255             }
    256         } finally {
    257             super.finalize();
    258         }
    259     }
    260 
    261     @Override
    262     public String toString() {
    263         return "Surface(name=" + mName + ")";
    264     }
    265 
    266     /**
    267      * Release the local reference to the server-side surface.
    268      * Always call release() when you're done with a Surface.
    269      * This will make the surface invalid.
    270      */
    271     public void release() {
    272         if (mNativeObject != 0) {
    273             nativeRelease(mNativeObject);
    274             mNativeObject = 0;
    275         }
    276         mCloseGuard.close();
    277     }
    278 
    279     /**
    280      * Free all server-side state associated with this surface and
    281      * release this object's reference.  This method can only be
    282      * called from the process that created the service.
    283      */
    284     public void destroy() {
    285         if (mNativeObject != 0) {
    286             nativeDestroy(mNativeObject);
    287             mNativeObject = 0;
    288         }
    289         mCloseGuard.close();
    290     }
    291 
    292     private void checkNotReleased() {
    293         if (mNativeObject == 0) throw new NullPointerException(
    294                 "mNativeObject is null. Have you called release() already?");
    295     }
    296 
    297     /*
    298      * set surface parameters.
    299      * needs to be inside open/closeTransaction block
    300      */
    301 
    302     /** start a transaction */
    303     public static void openTransaction() {
    304         nativeOpenTransaction();
    305     }
    306 
    307     /** end a transaction */
    308     public static void closeTransaction() {
    309         nativeCloseTransaction();
    310     }
    311 
    312     /** flag the transaction as an animation */
    313     public static void setAnimationTransaction() {
    314         nativeSetAnimationTransaction();
    315     }
    316 
    317     public void setLayer(int zorder) {
    318         checkNotReleased();
    319         nativeSetLayer(mNativeObject, zorder);
    320     }
    321 
    322     public void setPosition(float x, float y) {
    323         checkNotReleased();
    324         nativeSetPosition(mNativeObject, x, y);
    325     }
    326 
    327     public void setSize(int w, int h) {
    328         checkNotReleased();
    329         nativeSetSize(mNativeObject, w, h);
    330     }
    331 
    332     public void hide() {
    333         checkNotReleased();
    334         nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
    335     }
    336 
    337     public void show() {
    338         checkNotReleased();
    339         nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN);
    340     }
    341 
    342     public void setTransparentRegionHint(Region region) {
    343         checkNotReleased();
    344         nativeSetTransparentRegionHint(mNativeObject, region);
    345     }
    346 
    347     public void setAlpha(float alpha) {
    348         checkNotReleased();
    349         nativeSetAlpha(mNativeObject, alpha);
    350     }
    351 
    352     public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    353         checkNotReleased();
    354         nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy);
    355     }
    356 
    357     public void setFlags(int flags, int mask) {
    358         checkNotReleased();
    359         nativeSetFlags(mNativeObject, flags, mask);
    360     }
    361 
    362     public void setWindowCrop(Rect crop) {
    363         checkNotReleased();
    364         if (crop != null) {
    365             nativeSetWindowCrop(mNativeObject,
    366                 crop.left, crop.top, crop.right, crop.bottom);
    367         } else {
    368             nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0);
    369         }
    370     }
    371 
    372     public void setLayerStack(int layerStack) {
    373         checkNotReleased();
    374         nativeSetLayerStack(mNativeObject, layerStack);
    375     }
    376 
    377     /*
    378      * set display parameters.
    379      * needs to be inside open/closeTransaction block
    380      */
    381 
    382     /**
    383      * Describes the properties of a physical display known to surface flinger.
    384      */
    385     public static final class PhysicalDisplayInfo {
    386         public int width;
    387         public int height;
    388         public float refreshRate;
    389         public float density;
    390         public float xDpi;
    391         public float yDpi;
    392         public boolean secure;
    393 
    394         public PhysicalDisplayInfo() {
    395         }
    396 
    397         public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
    398             copyFrom(other);
    399         }
    400 
    401         @Override
    402         public boolean equals(Object o) {
    403             return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
    404         }
    405 
    406         public boolean equals(PhysicalDisplayInfo other) {
    407             return other != null
    408                     && width == other.width
    409                     && height == other.height
    410                     && refreshRate == other.refreshRate
    411                     && density == other.density
    412                     && xDpi == other.xDpi
    413                     && yDpi == other.yDpi
    414                     && secure == other.secure;
    415         }
    416 
    417         @Override
    418         public int hashCode() {
    419             return 0; // don't care
    420         }
    421 
    422         public void copyFrom(PhysicalDisplayInfo other) {
    423             width = other.width;
    424             height = other.height;
    425             refreshRate = other.refreshRate;
    426             density = other.density;
    427             xDpi = other.xDpi;
    428             yDpi = other.yDpi;
    429             secure = other.secure;
    430         }
    431 
    432         // For debugging purposes
    433         @Override
    434         public String toString() {
    435             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
    436                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
    437                     + "}";
    438         }
    439     }
    440 
    441     public static void unblankDisplay(IBinder displayToken) {
    442         if (displayToken == null) {
    443             throw new IllegalArgumentException("displayToken must not be null");
    444         }
    445         nativeUnblankDisplay(displayToken);
    446     }
    447 
    448     public static void blankDisplay(IBinder displayToken) {
    449         if (displayToken == null) {
    450             throw new IllegalArgumentException("displayToken must not be null");
    451         }
    452         nativeBlankDisplay(displayToken);
    453     }
    454 
    455     public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo) {
    456         if (displayToken == null) {
    457             throw new IllegalArgumentException("displayToken must not be null");
    458         }
    459         if (outInfo == null) {
    460             throw new IllegalArgumentException("outInfo must not be null");
    461         }
    462         return nativeGetDisplayInfo(displayToken, outInfo);
    463     }
    464 
    465     public static void setDisplayProjection(IBinder displayToken,
    466             int orientation, Rect layerStackRect, Rect displayRect) {
    467         if (displayToken == null) {
    468             throw new IllegalArgumentException("displayToken must not be null");
    469         }
    470         if (layerStackRect == null) {
    471             throw new IllegalArgumentException("layerStackRect must not be null");
    472         }
    473         if (displayRect == null) {
    474             throw new IllegalArgumentException("displayRect must not be null");
    475         }
    476         nativeSetDisplayProjection(displayToken, orientation,
    477                 layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
    478                 displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
    479     }
    480 
    481     public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
    482         if (displayToken == null) {
    483             throw new IllegalArgumentException("displayToken must not be null");
    484         }
    485         nativeSetDisplayLayerStack(displayToken, layerStack);
    486     }
    487 
    488     public static void setDisplaySurface(IBinder displayToken, Surface surface) {
    489         if (displayToken == null) {
    490             throw new IllegalArgumentException("displayToken must not be null");
    491         }
    492 
    493         if (surface != null) {
    494             synchronized (surface.mLock) {
    495                 nativeSetDisplaySurface(displayToken, surface.mNativeObject);
    496             }
    497         } else {
    498             nativeSetDisplaySurface(displayToken, 0);
    499         }
    500     }
    501 
    502     public static IBinder createDisplay(String name, boolean secure) {
    503         if (name == null) {
    504             throw new IllegalArgumentException("name must not be null");
    505         }
    506         return nativeCreateDisplay(name, secure);
    507     }
    508 
    509     public static void destroyDisplay(IBinder displayToken) {
    510         if (displayToken == null) {
    511             throw new IllegalArgumentException("displayToken must not be null");
    512         }
    513         nativeDestroyDisplay(displayToken);
    514     }
    515 
    516     public static IBinder getBuiltInDisplay(int builtInDisplayId) {
    517         return nativeGetBuiltInDisplay(builtInDisplayId);
    518     }
    519 
    520 
    521     /**
    522      * Copy the current screen contents into the provided {@link Surface}
    523      *
    524      * @param display The display to take the screenshot of.
    525      * @param consumer The {@link Surface} to take the screenshot into.
    526      * @param width The desired width of the returned bitmap; the raw
    527      * screen will be scaled down to this size.
    528      * @param height The desired height of the returned bitmap; the raw
    529      * screen will be scaled down to this size.
    530      * @param minLayer The lowest (bottom-most Z order) surface layer to
    531      * include in the screenshot.
    532      * @param maxLayer The highest (top-most Z order) surface layer to
    533      * include in the screenshot.
    534      */
    535     public static void screenshot(IBinder display, Surface consumer,
    536             int width, int height, int minLayer, int maxLayer) {
    537         screenshot(display, consumer, width, height, minLayer, maxLayer, false);
    538     }
    539 
    540     /**
    541      * Copy the current screen contents into the provided {@link Surface}
    542      *
    543      * @param display The display to take the screenshot of.
    544      * @param consumer The {@link Surface} to take the screenshot into.
    545      * @param width The desired width of the returned bitmap; the raw
    546      * screen will be scaled down to this size.
    547      * @param height The desired height of the returned bitmap; the raw
    548      * screen will be scaled down to this size.
    549      */
    550     public static void screenshot(IBinder display, Surface consumer,
    551             int width, int height) {
    552         screenshot(display, consumer, width, height, 0, 0, true);
    553     }
    554 
    555     /**
    556      * Copy the current screen contents into the provided {@link Surface}
    557      *
    558      * @param display The display to take the screenshot of.
    559      * @param consumer The {@link Surface} to take the screenshot into.
    560      */
    561     public static void screenshot(IBinder display, Surface consumer) {
    562         screenshot(display, consumer, 0, 0, 0, 0, true);
    563     }
    564 
    565 
    566     /**
    567      * Copy the current screen contents into a bitmap and return it.
    568      *
    569      * CAVEAT: Versions of screenshot that return a {@link Bitmap} can
    570      * be extremely slow; avoid use unless absolutely necessary; prefer
    571      * the versions that use a {@link Surface} instead, such as
    572      * {@link SurfaceControl#screenshot(IBinder, Surface)}.
    573      *
    574      * @param width The desired width of the returned bitmap; the raw
    575      * screen will be scaled down to this size.
    576      * @param height The desired height of the returned bitmap; the raw
    577      * screen will be scaled down to this size.
    578      * @param minLayer The lowest (bottom-most Z order) surface layer to
    579      * include in the screenshot.
    580      * @param maxLayer The highest (top-most Z order) surface layer to
    581      * include in the screenshot.
    582      * @return Returns a Bitmap containing the screen contents, or null
    583      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
    584      * possible, once its content is not needed anymore.
    585      */
    586     public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
    587         // TODO: should take the display as a parameter
    588         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
    589                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
    590         return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
    591     }
    592 
    593     /**
    594      * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
    595      * Surfaces in the screenshot.
    596      *
    597      * @param width The desired width of the returned bitmap; the raw
    598      * screen will be scaled down to this size.
    599      * @param height The desired height of the returned bitmap; the raw
    600      * screen will be scaled down to this size.
    601      * @return Returns a Bitmap containing the screen contents, or null
    602      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
    603      * possible, once its content is not needed anymore.
    604      */
    605     public static Bitmap screenshot(int width, int height) {
    606         // TODO: should take the display as a parameter
    607         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
    608                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
    609         return nativeScreenshot(displayToken, width, height, 0, 0, true);
    610     }
    611 
    612     private static void screenshot(IBinder display, Surface consumer,
    613             int width, int height, int minLayer, int maxLayer, boolean allLayers) {
    614         if (display == null) {
    615             throw new IllegalArgumentException("displayToken must not be null");
    616         }
    617         if (consumer == null) {
    618             throw new IllegalArgumentException("consumer must not be null");
    619         }
    620         nativeScreenshot(display, consumer, width, height, minLayer, maxLayer, allLayers);
    621     }
    622 
    623     private static void checkHeadless() {
    624         if (HEADLESS) {
    625             throw new UnsupportedOperationException("Device is headless");
    626         }
    627     }
    628 }
    629