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 static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
     20 
     21 import android.graphics.Bitmap;
     22 import android.graphics.GraphicBuffer;
     23 import android.graphics.Rect;
     24 import android.graphics.Region;
     25 import android.os.Binder;
     26 import android.os.IBinder;
     27 import android.util.Log;
     28 import android.view.Surface.OutOfResourcesException;
     29 
     30 import dalvik.system.CloseGuard;
     31 
     32 /**
     33  * SurfaceControl
     34  *  @hide
     35  */
     36 public class SurfaceControl {
     37     private static final String TAG = "SurfaceControl";
     38 
     39     private static native long nativeCreate(SurfaceSession session, String name,
     40             int w, int h, int format, int flags, long parentObject, int windowType, int ownerUid)
     41             throws OutOfResourcesException;
     42     private static native void nativeRelease(long nativeObject);
     43     private static native void nativeDestroy(long nativeObject);
     44     private static native void nativeDisconnect(long nativeObject);
     45 
     46     private static native Bitmap nativeScreenshot(IBinder displayToken,
     47             Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
     48             boolean allLayers, boolean useIdentityTransform, int rotation);
     49     private static native GraphicBuffer nativeScreenshotToBuffer(IBinder displayToken,
     50             Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
     51             boolean allLayers, boolean useIdentityTransform, int rotation);
     52     private static native void nativeScreenshot(IBinder displayToken, Surface consumer,
     53             Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
     54             boolean allLayers, boolean useIdentityTransform);
     55 
     56     private static native void nativeOpenTransaction();
     57     private static native void nativeCloseTransaction(boolean sync);
     58     private static native void nativeSetAnimationTransaction();
     59 
     60     private static native void nativeSetLayer(long nativeObject, int zorder);
     61     private static native void nativeSetRelativeLayer(long nativeObject, IBinder relativeTo,
     62             int zorder);
     63     private static native void nativeSetPosition(long nativeObject, float x, float y);
     64     private static native void nativeSetGeometryAppliesWithResize(long nativeObject);
     65     private static native void nativeSetSize(long nativeObject, int w, int h);
     66     private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
     67     private static native void nativeSetAlpha(long nativeObject, float alpha);
     68     private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx,
     69             float dtdy, float dsdy);
     70     private static native void nativeSetFlags(long nativeObject, int flags, int mask);
     71     private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
     72     private static native void nativeSetFinalCrop(long nativeObject, int l, int t, int r, int b);
     73     private static native void nativeSetLayerStack(long nativeObject, int layerStack);
     74 
     75     private static native boolean nativeClearContentFrameStats(long nativeObject);
     76     private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
     77     private static native boolean nativeClearAnimationFrameStats();
     78     private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
     79 
     80     private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
     81     private static native IBinder nativeCreateDisplay(String name, boolean secure);
     82     private static native void nativeDestroyDisplay(IBinder displayToken);
     83     private static native void nativeSetDisplaySurface(
     84             IBinder displayToken, long nativeSurfaceObject);
     85     private static native void nativeSetDisplayLayerStack(
     86             IBinder displayToken, int layerStack);
     87     private static native void nativeSetDisplayProjection(
     88             IBinder displayToken, int orientation,
     89             int l, int t, int r, int b,
     90             int L, int T, int R, int B);
     91     private static native void nativeSetDisplaySize(IBinder displayToken, int width, int height);
     92     private static native SurfaceControl.PhysicalDisplayInfo[] nativeGetDisplayConfigs(
     93             IBinder displayToken);
     94     private static native int nativeGetActiveConfig(IBinder displayToken);
     95     private static native boolean nativeSetActiveConfig(IBinder displayToken, int id);
     96     private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
     97     private static native int nativeGetActiveColorMode(IBinder displayToken);
     98     private static native boolean nativeSetActiveColorMode(IBinder displayToken,
     99             int colorMode);
    100     private static native void nativeSetDisplayPowerMode(
    101             IBinder displayToken, int mode);
    102     private static native void nativeDeferTransactionUntil(long nativeObject,
    103             IBinder handle, long frame);
    104     private static native void nativeDeferTransactionUntilSurface(long nativeObject,
    105             long surfaceObject, long frame);
    106     private static native void nativeReparentChildren(long nativeObject,
    107             IBinder handle);
    108     private static native void nativeSeverChildren(long nativeObject);
    109     private static native void nativeSetOverrideScalingMode(long nativeObject,
    110             int scalingMode);
    111     private static native IBinder nativeGetHandle(long nativeObject);
    112     private static native boolean nativeGetTransformToDisplayInverse(long nativeObject);
    113 
    114     private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
    115 
    116 
    117     private final CloseGuard mCloseGuard = CloseGuard.get();
    118     private final String mName;
    119     long mNativeObject; // package visibility only for Surface.java access
    120 
    121     /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
    122 
    123     /**
    124      * Surface creation flag: Surface is created hidden
    125      */
    126     public static final int HIDDEN = 0x00000004;
    127 
    128     /**
    129      * Surface creation flag: The surface contains secure content, special
    130      * measures will be taken to disallow the surface's content to be copied
    131      * from another process. In particular, screenshots and VNC servers will
    132      * be disabled, but other measures can take place, for instance the
    133      * surface might not be hardware accelerated.
    134      *
    135      */
    136     public static final int SECURE = 0x00000080;
    137 
    138     /**
    139      * Surface creation flag: Creates a surface where color components are interpreted
    140      * as "non pre-multiplied" by their alpha channel. Of course this flag is
    141      * meaningless for surfaces without an alpha channel. By default
    142      * surfaces are pre-multiplied, which means that each color component is
    143      * already multiplied by its alpha value. In this case the blending
    144      * equation used is:
    145      * <p>
    146      *    <code>DEST = SRC + DEST * (1-SRC_ALPHA)</code>
    147      * <p>
    148      * By contrast, non pre-multiplied surfaces use the following equation:
    149      * <p>
    150      *    <code>DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)</code>
    151      * <p>
    152      * pre-multiplied surfaces must always be used if transparent pixels are
    153      * composited on top of each-other into the surface. A pre-multiplied
    154      * surface can never lower the value of the alpha component of a given
    155      * pixel.
    156      * <p>
    157      * In some rare situations, a non pre-multiplied surface is preferable.
    158      *
    159      */
    160     public static final int NON_PREMULTIPLIED = 0x00000100;
    161 
    162     /**
    163      * Surface creation flag: Indicates that the surface must be considered opaque,
    164      * even if its pixel format is set to translucent. This can be useful if an
    165      * application needs full RGBA 8888 support for instance but will
    166      * still draw every pixel opaque.
    167      * <p>
    168      * This flag is ignored if setAlpha() is used to make the surface non-opaque.
    169      * Combined effects are (assuming a buffer format with an alpha channel):
    170      * <ul>
    171      * <li>OPAQUE + alpha(1.0) == opaque composition
    172      * <li>OPAQUE + alpha(0.x) == blended composition
    173      * <li>!OPAQUE + alpha(1.0) == blended composition
    174      * <li>!OPAQUE + alpha(0.x) == blended composition
    175      * </ul>
    176      * If the underlying buffer lacks an alpha channel, the OPAQUE flag is effectively
    177      * set automatically.
    178      */
    179     public static final int OPAQUE = 0x00000400;
    180 
    181     /**
    182      * Surface creation flag: Application requires a hardware-protected path to an
    183      * external display sink. If a hardware-protected path is not available,
    184      * then this surface will not be displayed on the external sink.
    185      *
    186      */
    187     public static final int PROTECTED_APP = 0x00000800;
    188 
    189     // 0x1000 is reserved for an independent DRM protected flag in framework
    190 
    191     /**
    192      * Surface creation flag: Window represents a cursor glyph.
    193      */
    194     public static final int CURSOR_WINDOW = 0x00002000;
    195 
    196     /**
    197      * Surface creation flag: Creates a normal surface.
    198      * This is the default.
    199      *
    200      */
    201     public static final int FX_SURFACE_NORMAL   = 0x00000000;
    202 
    203     /**
    204      * Surface creation flag: Creates a Dim surface.
    205      * Everything behind this surface is dimmed by the amount specified
    206      * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
    207      * doesn't have a backing store.
    208      *
    209      */
    210     public static final int FX_SURFACE_DIM = 0x00020000;
    211 
    212     /**
    213      * Mask used for FX values above.
    214      *
    215      */
    216     public static final int FX_SURFACE_MASK = 0x000F0000;
    217 
    218     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
    219 
    220     /**
    221      * Surface flag: Hide the surface.
    222      * Equivalent to calling hide().
    223      * Updates the value set during Surface creation (see {@link #HIDDEN}).
    224      */
    225     private static final int SURFACE_HIDDEN = 0x01;
    226 
    227     /**
    228      * Surface flag: composite without blending when possible.
    229      * Updates the value set during Surface creation (see {@link #OPAQUE}).
    230      */
    231     private static final int SURFACE_OPAQUE = 0x02;
    232 
    233 
    234     /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
    235      * these are different from the logical display ids used elsewhere in the framework */
    236 
    237     /**
    238      * Built-in physical display id: Main display.
    239      * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
    240      */
    241     public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
    242 
    243     /**
    244      * Built-in physical display id: Attached HDMI display.
    245      * Use only with {@link SurfaceControl#getBuiltInDisplay(int)}.
    246      */
    247     public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
    248 
    249     /* Display power modes * /
    250 
    251     /**
    252      * Display power mode off: used while blanking the screen.
    253      * Use only with {@link SurfaceControl#setDisplayPowerMode}.
    254      */
    255     public static final int POWER_MODE_OFF = 0;
    256 
    257     /**
    258      * Display power mode doze: used while putting the screen into low power mode.
    259      * Use only with {@link SurfaceControl#setDisplayPowerMode}.
    260      */
    261     public static final int POWER_MODE_DOZE = 1;
    262 
    263     /**
    264      * Display power mode normal: used while unblanking the screen.
    265      * Use only with {@link SurfaceControl#setDisplayPowerMode}.
    266      */
    267     public static final int POWER_MODE_NORMAL = 2;
    268 
    269     /**
    270      * Display power mode doze: used while putting the screen into a suspended
    271      * low power mode.  Use only with {@link SurfaceControl#setDisplayPowerMode}.
    272      */
    273     public static final int POWER_MODE_DOZE_SUSPEND = 3;
    274 
    275     /**
    276      * A value for windowType used to indicate that the window should be omitted from screenshots
    277      * and display mirroring. A temporary workaround until we express such things with
    278      * the hierarchy.
    279      * TODO: b/64227542
    280      * @hide
    281      */
    282     public static final int WINDOW_TYPE_DONT_SCREENSHOT = 441731;
    283 
    284     /**
    285      * Create a surface with a name.
    286      * <p>
    287      * The surface creation flags specify what kind of surface to create and
    288      * certain options such as whether the surface can be assumed to be opaque
    289      * and whether it should be initially hidden.  Surfaces should always be
    290      * created with the {@link #HIDDEN} flag set to ensure that they are not
    291      * made visible prematurely before all of the surface's properties have been
    292      * configured.
    293      * <p>
    294      * Good practice is to first create the surface with the {@link #HIDDEN} flag
    295      * specified, open a transaction, set the surface layer, layer stack, alpha,
    296      * and position, call {@link #show} if appropriate, and close the transaction.
    297      *
    298      * @param session The surface session, must not be null.
    299      * @param name The surface name, must not be null.
    300      * @param w The surface initial width.
    301      * @param h The surface initial height.
    302      * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
    303      * in the creation flags.
    304      * @param windowType The type of the window as specified in WindowManager.java.
    305      * @param ownerUid A unique per-app ID.
    306      *
    307      * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
    308      */
    309     public SurfaceControl(SurfaceSession session,
    310             String name, int w, int h, int format, int flags, int windowType, int ownerUid)
    311                     throws OutOfResourcesException {
    312         this(session, name, w, h, format, flags, null, windowType, ownerUid);
    313     }
    314 
    315     public SurfaceControl(SurfaceSession session,
    316             String name, int w, int h, int format, int flags)
    317                     throws OutOfResourcesException {
    318         this(session, name, w, h, format, flags, null, INVALID_WINDOW_TYPE, Binder.getCallingUid());
    319     }
    320 
    321     public SurfaceControl(SurfaceSession session, String name, int w, int h, int format, int flags,
    322             SurfaceControl parent, int windowType, int ownerUid)
    323                     throws OutOfResourcesException {
    324         if (session == null) {
    325             throw new IllegalArgumentException("session must not be null");
    326         }
    327         if (name == null) {
    328             throw new IllegalArgumentException("name must not be null");
    329         }
    330 
    331         if ((flags & SurfaceControl.HIDDEN) == 0) {
    332             Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
    333                     + "to ensure that they are not made visible prematurely before "
    334                     + "all of the surface's properties have been configured.  "
    335                     + "Set the other properties and make the surface visible within "
    336                     + "a transaction.  New surface name: " + name,
    337                     new Throwable());
    338         }
    339 
    340         mName = name;
    341         mNativeObject = nativeCreate(session, name, w, h, format, flags,
    342             parent != null ? parent.mNativeObject : 0, windowType, ownerUid);
    343         if (mNativeObject == 0) {
    344             throw new OutOfResourcesException(
    345                     "Couldn't allocate SurfaceControl native object");
    346         }
    347 
    348         mCloseGuard.open("release");
    349     }
    350 
    351     // This is a transfer constructor, useful for transferring a live SurfaceControl native
    352     // object to another Java wrapper which could have some different behavior, e.g.
    353     // event logging.
    354     public SurfaceControl(SurfaceControl other) {
    355         mName = other.mName;
    356         mNativeObject = other.mNativeObject;
    357         other.mCloseGuard.close();
    358         other.mNativeObject = 0;
    359         mCloseGuard.open("release");
    360     }
    361 
    362     @Override
    363     protected void finalize() throws Throwable {
    364         try {
    365             if (mCloseGuard != null) {
    366                 mCloseGuard.warnIfOpen();
    367             }
    368             if (mNativeObject != 0) {
    369                 nativeRelease(mNativeObject);
    370             }
    371         } finally {
    372             super.finalize();
    373         }
    374     }
    375 
    376     @Override
    377     public String toString() {
    378         return "Surface(name=" + mName + ")";
    379     }
    380 
    381     /**
    382      * Release the local reference to the server-side surface.
    383      * Always call release() when you're done with a Surface.
    384      * This will make the surface invalid.
    385      */
    386     public void release() {
    387         if (mNativeObject != 0) {
    388             nativeRelease(mNativeObject);
    389             mNativeObject = 0;
    390         }
    391         mCloseGuard.close();
    392     }
    393 
    394     /**
    395      * Free all server-side state associated with this surface and
    396      * release this object's reference.  This method can only be
    397      * called from the process that created the service.
    398      */
    399     public void destroy() {
    400         if (mNativeObject != 0) {
    401             nativeDestroy(mNativeObject);
    402             mNativeObject = 0;
    403         }
    404         mCloseGuard.close();
    405     }
    406 
    407     /**
    408      * Disconnect any client still connected to the surface.
    409      */
    410     public void disconnect() {
    411         if (mNativeObject != 0) {
    412             nativeDisconnect(mNativeObject);
    413         }
    414     }
    415 
    416     private void checkNotReleased() {
    417         if (mNativeObject == 0) throw new NullPointerException(
    418                 "mNativeObject is null. Have you called release() already?");
    419     }
    420 
    421     /*
    422      * set surface parameters.
    423      * needs to be inside open/closeTransaction block
    424      */
    425 
    426     /** start a transaction */
    427     public static void openTransaction() {
    428         nativeOpenTransaction();
    429     }
    430 
    431     /** end a transaction */
    432     public static void closeTransaction() {
    433         nativeCloseTransaction(false);
    434     }
    435 
    436     public static void closeTransactionSync() {
    437         nativeCloseTransaction(true);
    438     }
    439 
    440     public void deferTransactionUntil(IBinder handle, long frame) {
    441         if (frame > 0) {
    442             nativeDeferTransactionUntil(mNativeObject, handle, frame);
    443         }
    444     }
    445 
    446     public void deferTransactionUntil(Surface barrier, long frame) {
    447         if (frame > 0) {
    448             nativeDeferTransactionUntilSurface(mNativeObject, barrier.mNativeObject, frame);
    449         }
    450     }
    451 
    452     public void reparentChildren(IBinder newParentHandle) {
    453         nativeReparentChildren(mNativeObject, newParentHandle);
    454     }
    455 
    456     public void detachChildren() {
    457         nativeSeverChildren(mNativeObject);
    458     }
    459 
    460     public void setOverrideScalingMode(int scalingMode) {
    461         checkNotReleased();
    462         nativeSetOverrideScalingMode(mNativeObject, scalingMode);
    463     }
    464 
    465     public IBinder getHandle() {
    466         return nativeGetHandle(mNativeObject);
    467     }
    468 
    469     /** flag the transaction as an animation */
    470     public static void setAnimationTransaction() {
    471         nativeSetAnimationTransaction();
    472     }
    473 
    474     public void setLayer(int zorder) {
    475         checkNotReleased();
    476         nativeSetLayer(mNativeObject, zorder);
    477     }
    478 
    479     public void setRelativeLayer(IBinder relativeTo, int zorder) {
    480         checkNotReleased();
    481         nativeSetRelativeLayer(mNativeObject, relativeTo, zorder);
    482     }
    483 
    484     public void setPosition(float x, float y) {
    485         checkNotReleased();
    486         nativeSetPosition(mNativeObject, x, y);
    487     }
    488 
    489     /**
    490      * If the buffer size changes in this transaction, position and crop updates specified
    491      * in this transaction will not complete until a buffer of the new size
    492      * arrives. As transform matrix and size are already frozen in this fashion,
    493      * this enables totally freezing the surface until the resize has completed
    494      * (at which point the geometry influencing aspects of this transaction will then occur)
    495      */
    496     public void setGeometryAppliesWithResize() {
    497         checkNotReleased();
    498         nativeSetGeometryAppliesWithResize(mNativeObject);
    499     }
    500 
    501     public void setSize(int w, int h) {
    502         checkNotReleased();
    503         nativeSetSize(mNativeObject, w, h);
    504     }
    505 
    506     public void hide() {
    507         checkNotReleased();
    508         nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
    509     }
    510 
    511     public void show() {
    512         checkNotReleased();
    513         nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN);
    514     }
    515 
    516     public void setTransparentRegionHint(Region region) {
    517         checkNotReleased();
    518         nativeSetTransparentRegionHint(mNativeObject, region);
    519     }
    520 
    521     public boolean clearContentFrameStats() {
    522         checkNotReleased();
    523         return nativeClearContentFrameStats(mNativeObject);
    524     }
    525 
    526     public boolean getContentFrameStats(WindowContentFrameStats outStats) {
    527         checkNotReleased();
    528         return nativeGetContentFrameStats(mNativeObject, outStats);
    529     }
    530 
    531     public static boolean clearAnimationFrameStats() {
    532         return nativeClearAnimationFrameStats();
    533     }
    534 
    535     public static boolean getAnimationFrameStats(WindowAnimationFrameStats outStats) {
    536         return nativeGetAnimationFrameStats(outStats);
    537     }
    538 
    539     /**
    540      * Sets an alpha value for the entire Surface.  This value is combined with the
    541      * per-pixel alpha.  It may be used with opaque Surfaces.
    542      */
    543     public void setAlpha(float alpha) {
    544         checkNotReleased();
    545         nativeSetAlpha(mNativeObject, alpha);
    546     }
    547 
    548     public void setMatrix(float dsdx, float dtdx, float dtdy, float dsdy) {
    549         checkNotReleased();
    550         nativeSetMatrix(mNativeObject, dsdx, dtdx, dtdy, dsdy);
    551     }
    552 
    553     public void setWindowCrop(Rect crop) {
    554         checkNotReleased();
    555         if (crop != null) {
    556             nativeSetWindowCrop(mNativeObject,
    557                 crop.left, crop.top, crop.right, crop.bottom);
    558         } else {
    559             nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0);
    560         }
    561     }
    562 
    563     public void setFinalCrop(Rect crop) {
    564         checkNotReleased();
    565         if (crop != null) {
    566             nativeSetFinalCrop(mNativeObject,
    567                 crop.left, crop.top, crop.right, crop.bottom);
    568         } else {
    569             nativeSetFinalCrop(mNativeObject, 0, 0, 0, 0);
    570         }
    571     }
    572 
    573     public void setLayerStack(int layerStack) {
    574         checkNotReleased();
    575         nativeSetLayerStack(mNativeObject, layerStack);
    576     }
    577 
    578     /**
    579      * Sets the opacity of the surface.  Setting the flag is equivalent to creating the
    580      * Surface with the {@link #OPAQUE} flag.
    581      */
    582     public void setOpaque(boolean isOpaque) {
    583         checkNotReleased();
    584         if (isOpaque) {
    585             nativeSetFlags(mNativeObject, SURFACE_OPAQUE, SURFACE_OPAQUE);
    586         } else {
    587             nativeSetFlags(mNativeObject, 0, SURFACE_OPAQUE);
    588         }
    589     }
    590 
    591     /**
    592      * Sets the security of the surface.  Setting the flag is equivalent to creating the
    593      * Surface with the {@link #SECURE} flag.
    594      */
    595     public void setSecure(boolean isSecure) {
    596         checkNotReleased();
    597         if (isSecure) {
    598             nativeSetFlags(mNativeObject, SECURE, SECURE);
    599         } else {
    600             nativeSetFlags(mNativeObject, 0, SECURE);
    601         }
    602     }
    603 
    604     /*
    605      * set display parameters.
    606      * needs to be inside open/closeTransaction block
    607      */
    608 
    609     /**
    610      * Describes the properties of a physical display known to surface flinger.
    611      */
    612     public static final class PhysicalDisplayInfo {
    613         public int width;
    614         public int height;
    615         public float refreshRate;
    616         public float density;
    617         public float xDpi;
    618         public float yDpi;
    619         public boolean secure;
    620         public long appVsyncOffsetNanos;
    621         public long presentationDeadlineNanos;
    622 
    623         public PhysicalDisplayInfo() {
    624         }
    625 
    626         public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
    627             copyFrom(other);
    628         }
    629 
    630         @Override
    631         public boolean equals(Object o) {
    632             return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
    633         }
    634 
    635         public boolean equals(PhysicalDisplayInfo other) {
    636             return other != null
    637                     && width == other.width
    638                     && height == other.height
    639                     && refreshRate == other.refreshRate
    640                     && density == other.density
    641                     && xDpi == other.xDpi
    642                     && yDpi == other.yDpi
    643                     && secure == other.secure
    644                     && appVsyncOffsetNanos == other.appVsyncOffsetNanos
    645                     && presentationDeadlineNanos == other.presentationDeadlineNanos;
    646         }
    647 
    648         @Override
    649         public int hashCode() {
    650             return 0; // don't care
    651         }
    652 
    653         public void copyFrom(PhysicalDisplayInfo other) {
    654             width = other.width;
    655             height = other.height;
    656             refreshRate = other.refreshRate;
    657             density = other.density;
    658             xDpi = other.xDpi;
    659             yDpi = other.yDpi;
    660             secure = other.secure;
    661             appVsyncOffsetNanos = other.appVsyncOffsetNanos;
    662             presentationDeadlineNanos = other.presentationDeadlineNanos;
    663         }
    664 
    665         // For debugging purposes
    666         @Override
    667         public String toString() {
    668             return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
    669                     + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
    670                     + ", appVsyncOffset " + appVsyncOffsetNanos
    671                     + ", bufferDeadline " + presentationDeadlineNanos + "}";
    672         }
    673     }
    674 
    675     public static void setDisplayPowerMode(IBinder displayToken, int mode) {
    676         if (displayToken == null) {
    677             throw new IllegalArgumentException("displayToken must not be null");
    678         }
    679         nativeSetDisplayPowerMode(displayToken, mode);
    680     }
    681 
    682     public static SurfaceControl.PhysicalDisplayInfo[] getDisplayConfigs(IBinder displayToken) {
    683         if (displayToken == null) {
    684             throw new IllegalArgumentException("displayToken must not be null");
    685         }
    686         return nativeGetDisplayConfigs(displayToken);
    687     }
    688 
    689     public static int getActiveConfig(IBinder displayToken) {
    690         if (displayToken == null) {
    691             throw new IllegalArgumentException("displayToken must not be null");
    692         }
    693         return nativeGetActiveConfig(displayToken);
    694     }
    695 
    696     public static boolean setActiveConfig(IBinder displayToken, int id) {
    697         if (displayToken == null) {
    698             throw new IllegalArgumentException("displayToken must not be null");
    699         }
    700         return nativeSetActiveConfig(displayToken, id);
    701     }
    702 
    703     public static int[] getDisplayColorModes(IBinder displayToken) {
    704         if (displayToken == null) {
    705             throw new IllegalArgumentException("displayToken must not be null");
    706         }
    707         return nativeGetDisplayColorModes(displayToken);
    708     }
    709 
    710     public static int getActiveColorMode(IBinder displayToken) {
    711         if (displayToken == null) {
    712             throw new IllegalArgumentException("displayToken must not be null");
    713         }
    714         return nativeGetActiveColorMode(displayToken);
    715     }
    716 
    717     public static boolean setActiveColorMode(IBinder displayToken, int colorMode) {
    718         if (displayToken == null) {
    719             throw new IllegalArgumentException("displayToken must not be null");
    720         }
    721         return nativeSetActiveColorMode(displayToken, colorMode);
    722     }
    723 
    724     public static void setDisplayProjection(IBinder displayToken,
    725             int orientation, Rect layerStackRect, Rect displayRect) {
    726         if (displayToken == null) {
    727             throw new IllegalArgumentException("displayToken must not be null");
    728         }
    729         if (layerStackRect == null) {
    730             throw new IllegalArgumentException("layerStackRect must not be null");
    731         }
    732         if (displayRect == null) {
    733             throw new IllegalArgumentException("displayRect must not be null");
    734         }
    735         nativeSetDisplayProjection(displayToken, orientation,
    736                 layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom,
    737                 displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
    738     }
    739 
    740     public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
    741         if (displayToken == null) {
    742             throw new IllegalArgumentException("displayToken must not be null");
    743         }
    744         nativeSetDisplayLayerStack(displayToken, layerStack);
    745     }
    746 
    747     public static void setDisplaySurface(IBinder displayToken, Surface surface) {
    748         if (displayToken == null) {
    749             throw new IllegalArgumentException("displayToken must not be null");
    750         }
    751 
    752         if (surface != null) {
    753             synchronized (surface.mLock) {
    754                 nativeSetDisplaySurface(displayToken, surface.mNativeObject);
    755             }
    756         } else {
    757             nativeSetDisplaySurface(displayToken, 0);
    758         }
    759     }
    760 
    761     public static void setDisplaySize(IBinder displayToken, int width, int height) {
    762         if (displayToken == null) {
    763             throw new IllegalArgumentException("displayToken must not be null");
    764         }
    765         if (width <= 0 || height <= 0) {
    766             throw new IllegalArgumentException("width and height must be positive");
    767         }
    768 
    769         nativeSetDisplaySize(displayToken, width, height);
    770     }
    771 
    772     public static Display.HdrCapabilities getHdrCapabilities(IBinder displayToken) {
    773         if (displayToken == null) {
    774             throw new IllegalArgumentException("displayToken must not be null");
    775         }
    776         return nativeGetHdrCapabilities(displayToken);
    777     }
    778 
    779     public static IBinder createDisplay(String name, boolean secure) {
    780         if (name == null) {
    781             throw new IllegalArgumentException("name must not be null");
    782         }
    783         return nativeCreateDisplay(name, secure);
    784     }
    785 
    786     public static void destroyDisplay(IBinder displayToken) {
    787         if (displayToken == null) {
    788             throw new IllegalArgumentException("displayToken must not be null");
    789         }
    790         nativeDestroyDisplay(displayToken);
    791     }
    792 
    793     public static IBinder getBuiltInDisplay(int builtInDisplayId) {
    794         return nativeGetBuiltInDisplay(builtInDisplayId);
    795     }
    796 
    797     /**
    798      * Copy the current screen contents into the provided {@link Surface}
    799      *
    800      * @param display The display to take the screenshot of.
    801      * @param consumer The {@link Surface} to take the screenshot into.
    802      * @param width The desired width of the returned bitmap; the raw
    803      * screen will be scaled down to this size.
    804      * @param height The desired height of the returned bitmap; the raw
    805      * screen will be scaled down to this size.
    806      * @param minLayer The lowest (bottom-most Z order) surface layer to
    807      * include in the screenshot.
    808      * @param maxLayer The highest (top-most Z order) surface layer to
    809      * include in the screenshot.
    810      * @param useIdentityTransform Replace whatever transformation (rotation,
    811      * scaling, translation) the surface layers are currently using with the
    812      * identity transformation while taking the screenshot.
    813      */
    814     public static void screenshot(IBinder display, Surface consumer,
    815             int width, int height, int minLayer, int maxLayer,
    816             boolean useIdentityTransform) {
    817         screenshot(display, consumer, new Rect(), width, height, minLayer, maxLayer,
    818                 false, useIdentityTransform);
    819     }
    820 
    821     /**
    822      * Copy the current screen contents into the provided {@link Surface}
    823      *
    824      * @param display The display to take the screenshot of.
    825      * @param consumer The {@link Surface} to take the screenshot into.
    826      * @param width The desired width of the returned bitmap; the raw
    827      * screen will be scaled down to this size.
    828      * @param height The desired height of the returned bitmap; the raw
    829      * screen will be scaled down to this size.
    830      */
    831     public static void screenshot(IBinder display, Surface consumer,
    832             int width, int height) {
    833         screenshot(display, consumer, new Rect(), width, height, 0, 0, true, false);
    834     }
    835 
    836     /**
    837      * Copy the current screen contents into the provided {@link Surface}
    838      *
    839      * @param display The display to take the screenshot of.
    840      * @param consumer The {@link Surface} to take the screenshot into.
    841      */
    842     public static void screenshot(IBinder display, Surface consumer) {
    843         screenshot(display, consumer, new Rect(), 0, 0, 0, 0, true, false);
    844     }
    845 
    846     /**
    847      * Copy the current screen contents into a bitmap and return it.
    848      *
    849      * CAVEAT: Versions of screenshot that return a {@link Bitmap} can
    850      * be extremely slow; avoid use unless absolutely necessary; prefer
    851      * the versions that use a {@link Surface} instead, such as
    852      * {@link SurfaceControl#screenshot(IBinder, Surface)}.
    853      *
    854      * @param sourceCrop The portion of the screen to capture into the Bitmap;
    855      * caller may pass in 'new Rect()' if no cropping is desired.
    856      * @param width The desired width of the returned bitmap; the raw
    857      * screen will be scaled down to this size.
    858      * @param height The desired height of the returned bitmap; the raw
    859      * screen will be scaled down to this size.
    860      * @param minLayer The lowest (bottom-most Z order) surface layer to
    861      * include in the screenshot.
    862      * @param maxLayer The highest (top-most Z order) surface layer to
    863      * include in the screenshot.
    864      * @param useIdentityTransform Replace whatever transformation (rotation,
    865      * scaling, translation) the surface layers are currently using with the
    866      * identity transformation while taking the screenshot.
    867      * @param rotation Apply a custom clockwise rotation to the screenshot, i.e.
    868      * Surface.ROTATION_0,90,180,270. Surfaceflinger will always take
    869      * screenshots in its native portrait orientation by default, so this is
    870      * useful for returning screenshots that are independent of device
    871      * orientation.
    872      * @return Returns a Bitmap containing the screen contents, or null
    873      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
    874      * possible, once its content is not needed anymore.
    875      */
    876     public static Bitmap screenshot(Rect sourceCrop, int width, int height,
    877             int minLayer, int maxLayer, boolean useIdentityTransform,
    878             int rotation) {
    879         // TODO: should take the display as a parameter
    880         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
    881                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
    882         return nativeScreenshot(displayToken, sourceCrop, width, height,
    883                 minLayer, maxLayer, false, useIdentityTransform, rotation);
    884     }
    885 
    886     /**
    887      * Like {@link SurfaceControl#screenshot(Rect, int, int, int, int, boolean, int)}
    888      * but returns a GraphicBuffer.
    889      */
    890     public static GraphicBuffer screenshotToBuffer(Rect sourceCrop, int width, int height,
    891             int minLayer, int maxLayer, boolean useIdentityTransform,
    892             int rotation) {
    893         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
    894                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
    895         return nativeScreenshotToBuffer(displayToken, sourceCrop, width, height,
    896                 minLayer, maxLayer, false, useIdentityTransform, rotation);
    897     }
    898 
    899     /**
    900      * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
    901      * includes all Surfaces in the screenshot.
    902      *
    903      * @param width The desired width of the returned bitmap; the raw
    904      * screen will be scaled down to this size.
    905      * @param height The desired height of the returned bitmap; the raw
    906      * screen will be scaled down to this size.
    907      * @return Returns a Bitmap containing the screen contents, or null
    908      * if an error occurs. Make sure to call Bitmap.recycle() as soon as
    909      * possible, once its content is not needed anymore.
    910      */
    911     public static Bitmap screenshot(int width, int height) {
    912         // TODO: should take the display as a parameter
    913         IBinder displayToken = SurfaceControl.getBuiltInDisplay(
    914                 SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
    915         return nativeScreenshot(displayToken, new Rect(), width, height, 0, 0, true,
    916                 false, Surface.ROTATION_0);
    917     }
    918 
    919     private static void screenshot(IBinder display, Surface consumer, Rect sourceCrop,
    920             int width, int height, int minLayer, int maxLayer, boolean allLayers,
    921             boolean useIdentityTransform) {
    922         if (display == null) {
    923             throw new IllegalArgumentException("displayToken must not be null");
    924         }
    925         if (consumer == null) {
    926             throw new IllegalArgumentException("consumer must not be null");
    927         }
    928         nativeScreenshot(display, consumer, sourceCrop, width, height,
    929                 minLayer, maxLayer, allLayers, useIdentityTransform);
    930     }
    931 }
    932