Home | History | Annotate | Download | only in internal
      1 /*
      2  * Copyright (C) 2012 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 org.robolectric.android.internal;
     18 
     19 import static android.os.Build.VERSION_CODES.JELLY_BEAN_MR2;
     20 import static android.os.Build.VERSION_CODES.KITKAT;
     21 import static android.os.Build.VERSION_CODES.LOLLIPOP;
     22 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
     23 import static android.os.Build.VERSION_CODES.M;
     24 import static android.os.Build.VERSION_CODES.N;
     25 import static android.os.Build.VERSION_CODES.N_MR1;
     26 import static android.os.Build.VERSION_CODES.O;
     27 
     28 import android.util.ArraySet;
     29 import android.view.Display;
     30 import android.view.DisplayInfo;
     31 import android.view.Surface;
     32 import java.util.Arrays;
     33 import java.util.Objects;
     34 import org.robolectric.RuntimeEnvironment;
     35 
     36 /**
     37  * Describes the characteristics of a particular logical display.
     38  *
     39  * Robolectric internal (for now), do not use.
     40  */
     41 public final class DisplayConfig {
     42   /**
     43    * The surface flinger layer stack associated with this logical display.
     44    */
     45   public int layerStack;
     46 
     47   /**
     48    * Display flags.
     49    */
     50   public int flags;
     51 
     52   /**
     53    * Display type.
     54    */
     55   public int type;
     56 
     57   /**
     58    * Display address, or null if none.
     59    * Interpretation varies by display type.
     60    */
     61   public String address;
     62 
     63   /**
     64    * The human-readable name of the display.
     65    */
     66   public String name;
     67 
     68   /**
     69    * Unique identifier for the display. Shouldn't be displayed to the user.
     70    */
     71   public String uniqueId;
     72 
     73   /**
     74    * The width of the portion of the display that is available to applications, in pixels.
     75    * Represents the size of the display minus any system decorations.
     76    */
     77   public int appWidth;
     78 
     79   /**
     80    * The height of the portion of the display that is available to applications, in pixels.
     81    * Represents the size of the display minus any system decorations.
     82    */
     83   public int appHeight;
     84 
     85   /**
     86    * The smallest value of {@link #appWidth} that an application is likely to encounter,
     87    * in pixels, excepting cases where the width may be even smaller due to the presence
     88    * of a soft keyboard, for example.
     89    */
     90   public int smallestNominalAppWidth;
     91 
     92   /**
     93    * The smallest value of {@link #appHeight} that an application is likely to encounter,
     94    * in pixels, excepting cases where the height may be even smaller due to the presence
     95    * of a soft keyboard, for example.
     96    */
     97   public int smallestNominalAppHeight;
     98 
     99   /**
    100    * The largest value of {@link #appWidth} that an application is likely to encounter,
    101    * in pixels, excepting cases where the width may be even larger due to system decorations
    102    * such as the status bar being hidden, for example.
    103    */
    104   public int largestNominalAppWidth;
    105 
    106   /**
    107    * The largest value of {@link #appHeight} that an application is likely to encounter,
    108    * in pixels, excepting cases where the height may be even larger due to system decorations
    109    * such as the status bar being hidden, for example.
    110    */
    111   public int largestNominalAppHeight;
    112 
    113   /**
    114    * The logical width of the display, in pixels.
    115    * Represents the usable size of the display which may be smaller than the
    116    * physical size when the system is emulating a smaller display.
    117    */
    118   public int logicalWidth;
    119 
    120   /**
    121    * The logical height of the display, in pixels.
    122    * Represents the usable size of the display which may be smaller than the
    123    * physical size when the system is emulating a smaller display.
    124    */
    125   public int logicalHeight;
    126 
    127   /**
    128    * @hide
    129    * Number of overscan pixels on the left side of the display.
    130    */
    131   public int overscanLeft;
    132 
    133   /**
    134    * @hide
    135    * Number of overscan pixels on the top side of the display.
    136    */
    137   public int overscanTop;
    138 
    139   /**
    140    * @hide
    141    * Number of overscan pixels on the right side of the display.
    142    */
    143   public int overscanRight;
    144 
    145   /**
    146    * @hide
    147    * Number of overscan pixels on the bottom side of the display.
    148    */
    149   public int overscanBottom;
    150 
    151   /**
    152    * The rotation of the display relative to its natural orientation.
    153    * May be one of {@link Surface#ROTATION_0},
    154    * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180},
    155    * {@link Surface#ROTATION_270}.
    156    * <p>
    157    * The value of this field is indeterminate if the logical display is presented on
    158    * more than one physical display.
    159    * </p>
    160    */
    161   @Surface.Rotation
    162   public int rotation;
    163 
    164   /**
    165    * The active display mode.
    166    */
    167   public int modeId;
    168 
    169   /**
    170    * The default display mode.
    171    */
    172   public int defaultModeId;
    173 
    174   /**
    175    * The supported modes of this display.
    176    */
    177   public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
    178 
    179   /** The active color mode. */
    180   public int colorMode;
    181 
    182   /** The list of supported color modes */
    183   public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
    184 
    185   /** The display's HDR capabilities */
    186   public Display.HdrCapabilities hdrCapabilities;
    187 
    188   /**
    189    * The logical display density which is the basis for density-independent
    190    * pixels.
    191    */
    192   public int logicalDensityDpi;
    193 
    194   /**
    195    * The exact physical pixels per inch of the screen in the X dimension.
    196    * <p>
    197    * The value of this field is indeterminate if the logical display is presented on
    198    * more than one physical display.
    199    * </p>
    200    */
    201   public float physicalXDpi;
    202 
    203   /**
    204    * The exact physical pixels per inch of the screen in the Y dimension.
    205    * <p>
    206    * The value of this field is indeterminate if the logical display is presented on
    207    * more than one physical display.
    208    * </p>
    209    */
    210   public float physicalYDpi;
    211 
    212   /**
    213    * This is a positive value indicating the phase offset of the VSYNC events provided by
    214    * Choreographer relative to the display refresh.  For example, if Choreographer reports
    215    * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
    216    */
    217   public long appVsyncOffsetNanos;
    218 
    219   /**
    220    * This is how far in advance a buffer must be queued for presentation at
    221    * a given time.  If you want a buffer to appear on the screen at
    222    * time N, you must submit the buffer before (N - bufferDeadlineNanos).
    223    */
    224   public long presentationDeadlineNanos;
    225 
    226   /**
    227    * The state of the display, such as {@link Display#STATE_ON}.
    228    */
    229   public int state;
    230 
    231   /**
    232    * The UID of the application that owns this display, or zero if it is owned by the system.
    233    * <p>
    234    * If the display is private, then only the owner can use it.
    235    * </p>
    236    */
    237   public int ownerUid;
    238 
    239   /**
    240    * The package name of the application that owns this display, or null if it is
    241    * owned by the system.
    242    * <p>
    243    * If the display is private, then only the owner can use it.
    244    * </p>
    245    */
    246   public String ownerPackageName;
    247 
    248   /**
    249    * @hide
    250    * Get current remove mode of the display - what actions should be performed with the display's
    251    * content when it is removed.
    252    *
    253    * @see Display#getRemoveMode()
    254    */
    255   public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
    256 
    257   public DisplayConfig() {
    258   }
    259 
    260   public DisplayConfig(DisplayConfig other) {
    261     copyFrom(other);
    262   }
    263 
    264   public DisplayConfig(DisplayInfo other) {
    265     layerStack = other.layerStack;
    266     flags = other.flags;
    267     type = other.type;
    268     address = other.address;
    269     name = other.name;
    270     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
    271       uniqueId = other.uniqueId;
    272     }
    273     appWidth = other.appWidth;
    274     appHeight = other.appHeight;
    275     smallestNominalAppWidth = other.smallestNominalAppWidth;
    276     smallestNominalAppHeight = other.smallestNominalAppHeight;
    277     largestNominalAppWidth = other.largestNominalAppWidth;
    278     largestNominalAppHeight = other.largestNominalAppHeight;
    279     logicalWidth = other.logicalWidth;
    280     logicalHeight = other.logicalHeight;
    281     if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR2) {
    282       overscanLeft = other.overscanLeft;
    283       overscanTop = other.overscanTop;
    284       overscanRight = other.overscanRight;
    285       overscanBottom = other.overscanBottom;
    286     }
    287     rotation = other.rotation;
    288     if (RuntimeEnvironment.getApiLevel() >= M) {
    289       modeId = other.modeId;
    290       defaultModeId = other.defaultModeId;
    291       supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
    292     }
    293     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
    294       colorMode = other.colorMode;
    295       supportedColorModes = Arrays.copyOf(
    296           other.supportedColorModes, other.supportedColorModes.length);
    297     }
    298     if (RuntimeEnvironment.getApiLevel() >= N) {
    299       hdrCapabilities = other.hdrCapabilities;
    300     }
    301     logicalDensityDpi = other.logicalDensityDpi;
    302     physicalXDpi = other.physicalXDpi;
    303     physicalYDpi = other.physicalYDpi;
    304     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) {
    305       appVsyncOffsetNanos = other.appVsyncOffsetNanos;
    306       presentationDeadlineNanos = other.presentationDeadlineNanos;
    307       state = other.state;
    308     }
    309     if (RuntimeEnvironment.getApiLevel() >= KITKAT) {
    310       ownerUid = other.ownerUid;
    311       ownerPackageName = other.ownerPackageName;
    312     }
    313     if (RuntimeEnvironment.getApiLevel() >= O) {
    314       removeMode = other.removeMode;
    315     }
    316   }
    317 
    318   @Override
    319   public boolean equals(Object o) {
    320     return o instanceof DisplayConfig && equals((DisplayConfig)o);
    321   }
    322 
    323   public boolean equals(DisplayConfig other) {
    324     return other != null
    325         && layerStack == other.layerStack
    326         && flags == other.flags
    327         && type == other.type
    328         && Objects.equals(address, other.address)
    329         && Objects.equals(uniqueId, other.uniqueId)
    330         && appWidth == other.appWidth
    331         && appHeight == other.appHeight
    332         && smallestNominalAppWidth == other.smallestNominalAppWidth
    333         && smallestNominalAppHeight == other.smallestNominalAppHeight
    334         && largestNominalAppWidth == other.largestNominalAppWidth
    335         && largestNominalAppHeight == other.largestNominalAppHeight
    336         && logicalWidth == other.logicalWidth
    337         && logicalHeight == other.logicalHeight
    338         && overscanLeft == other.overscanLeft
    339         && overscanTop == other.overscanTop
    340         && overscanRight == other.overscanRight
    341         && overscanBottom == other.overscanBottom
    342         && rotation == other.rotation
    343         && modeId == other.modeId
    344         && defaultModeId == other.defaultModeId
    345         && colorMode == other.colorMode
    346         && Arrays.equals(supportedColorModes, other.supportedColorModes)
    347         && Objects.equals(hdrCapabilities, other.hdrCapabilities)
    348         && logicalDensityDpi == other.logicalDensityDpi
    349         && physicalXDpi == other.physicalXDpi
    350         && physicalYDpi == other.physicalYDpi
    351         && appVsyncOffsetNanos == other.appVsyncOffsetNanos
    352         && presentationDeadlineNanos == other.presentationDeadlineNanos
    353         && state == other.state
    354         && ownerUid == other.ownerUid
    355         && Objects.equals(ownerPackageName, other.ownerPackageName)
    356         && removeMode == other.removeMode;
    357   }
    358 
    359   @Override
    360   public int hashCode() {
    361     return 0; // don't care
    362   }
    363 
    364   public void copyFrom(DisplayConfig other) {
    365     layerStack = other.layerStack;
    366     flags = other.flags;
    367     type = other.type;
    368     address = other.address;
    369     name = other.name;
    370     uniqueId = other.uniqueId;
    371     appWidth = other.appWidth;
    372     appHeight = other.appHeight;
    373     smallestNominalAppWidth = other.smallestNominalAppWidth;
    374     smallestNominalAppHeight = other.smallestNominalAppHeight;
    375     largestNominalAppWidth = other.largestNominalAppWidth;
    376     largestNominalAppHeight = other.largestNominalAppHeight;
    377     logicalWidth = other.logicalWidth;
    378     logicalHeight = other.logicalHeight;
    379     overscanLeft = other.overscanLeft;
    380     overscanTop = other.overscanTop;
    381     overscanRight = other.overscanRight;
    382     overscanBottom = other.overscanBottom;
    383     rotation = other.rotation;
    384     modeId = other.modeId;
    385     defaultModeId = other.defaultModeId;
    386     supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
    387     colorMode = other.colorMode;
    388     supportedColorModes = Arrays.copyOf(
    389         other.supportedColorModes, other.supportedColorModes.length);
    390     hdrCapabilities = other.hdrCapabilities;
    391     logicalDensityDpi = other.logicalDensityDpi;
    392     physicalXDpi = other.physicalXDpi;
    393     physicalYDpi = other.physicalYDpi;
    394     appVsyncOffsetNanos = other.appVsyncOffsetNanos;
    395     presentationDeadlineNanos = other.presentationDeadlineNanos;
    396     state = other.state;
    397     ownerUid = other.ownerUid;
    398     ownerPackageName = other.ownerPackageName;
    399     removeMode = other.removeMode;
    400   }
    401 
    402   public void copyTo(DisplayInfo other) {
    403     other.layerStack = layerStack;
    404     other.flags = flags;
    405     other.type = type;
    406     other.address = address;
    407     other.name = name;
    408     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
    409       other.uniqueId = uniqueId;
    410     }
    411     other.appWidth = appWidth;
    412     other.appHeight = appHeight;
    413     other.smallestNominalAppWidth = smallestNominalAppWidth;
    414     other.smallestNominalAppHeight = smallestNominalAppHeight;
    415     other.largestNominalAppWidth = largestNominalAppWidth;
    416     other.largestNominalAppHeight = largestNominalAppHeight;
    417     other.logicalWidth = logicalWidth;
    418     other.logicalHeight = logicalHeight;
    419     if (RuntimeEnvironment.getApiLevel() >= JELLY_BEAN_MR2) {
    420       other.overscanLeft = overscanLeft;
    421       other.overscanTop = overscanTop;
    422       other.overscanRight = overscanRight;
    423       other.overscanBottom = overscanBottom;
    424     }
    425     other.rotation = rotation;
    426     if (RuntimeEnvironment.getApiLevel() >= M) {
    427       other.modeId = modeId;
    428       other.defaultModeId = defaultModeId;
    429       other.supportedModes = Arrays.copyOf(supportedModes, supportedModes.length);
    430     }
    431     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
    432       other.colorMode = colorMode;
    433       other.supportedColorModes = Arrays.copyOf(
    434           supportedColorModes, supportedColorModes.length);
    435     }
    436     if (RuntimeEnvironment.getApiLevel() >= N) {
    437       other.hdrCapabilities = hdrCapabilities;
    438     }
    439     other.logicalDensityDpi = logicalDensityDpi;
    440     other.physicalXDpi = physicalXDpi;
    441     other.physicalYDpi = physicalYDpi;
    442     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) {
    443       other.appVsyncOffsetNanos = appVsyncOffsetNanos;
    444       other.presentationDeadlineNanos = presentationDeadlineNanos;
    445       other.state = state;
    446     }
    447     if (RuntimeEnvironment.getApiLevel() >= KITKAT) {
    448       other.ownerUid = ownerUid;
    449       other.ownerPackageName = ownerPackageName;
    450     }
    451     if (RuntimeEnvironment.getApiLevel() >= O) {
    452       other.removeMode = removeMode;
    453     }
    454   }
    455 
    456   // For debugging purposes
    457   @Override
    458   public String toString() {
    459     StringBuilder sb = new StringBuilder();
    460     sb.append("DisplayConfig{\"");
    461     sb.append(name);
    462     sb.append("\", uniqueId \"");
    463     sb.append(uniqueId);
    464     sb.append("\", app ");
    465     sb.append(appWidth);
    466     sb.append(" x ");
    467     sb.append(appHeight);
    468     sb.append(", real ");
    469     sb.append(logicalWidth);
    470     sb.append(" x ");
    471     sb.append(logicalHeight);
    472     if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) {
    473       sb.append(", overscan (");
    474       sb.append(overscanLeft);
    475       sb.append(",");
    476       sb.append(overscanTop);
    477       sb.append(",");
    478       sb.append(overscanRight);
    479       sb.append(",");
    480       sb.append(overscanBottom);
    481       sb.append(")");
    482     }
    483     sb.append(", largest app ");
    484     sb.append(largestNominalAppWidth);
    485     sb.append(" x ");
    486     sb.append(largestNominalAppHeight);
    487     sb.append(", smallest app ");
    488     sb.append(smallestNominalAppWidth);
    489     sb.append(" x ");
    490     sb.append(smallestNominalAppHeight);
    491     sb.append(", mode ");
    492     sb.append(modeId);
    493     sb.append(", defaultMode ");
    494     sb.append(defaultModeId);
    495     sb.append(", modes ");
    496     sb.append(Arrays.toString(supportedModes));
    497     sb.append(", colorMode ");
    498     sb.append(colorMode);
    499     sb.append(", supportedColorModes ");
    500     sb.append(Arrays.toString(supportedColorModes));
    501     sb.append(", hdrCapabilities ");
    502     sb.append(hdrCapabilities);
    503     sb.append(", rotation ");
    504     sb.append(rotation);
    505     sb.append(", density ");
    506     sb.append(logicalDensityDpi);
    507     sb.append(" (");
    508     sb.append(physicalXDpi);
    509     sb.append(" x ");
    510     sb.append(physicalYDpi);
    511     sb.append(") dpi, layerStack ");
    512     sb.append(layerStack);
    513     sb.append(", appVsyncOff ");
    514     sb.append(appVsyncOffsetNanos);
    515     sb.append(", presDeadline ");
    516     sb.append(presentationDeadlineNanos);
    517     sb.append(", type ");
    518     sb.append(Display.typeToString(type));
    519     if (address != null) {
    520       sb.append(", address ").append(address);
    521     }
    522     sb.append(", state ");
    523     sb.append(Display.stateToString(state));
    524     if (ownerUid != 0 || ownerPackageName != null) {
    525       sb.append(", owner ").append(ownerPackageName);
    526       sb.append(" (uid ").append(ownerUid).append(")");
    527     }
    528     sb.append(flagsToString(flags));
    529     sb.append(", removeMode ");
    530     sb.append(removeMode);
    531     sb.append("}");
    532     return sb.toString();
    533   }
    534 
    535   private static String flagsToString(int flags) {
    536     StringBuilder result = new StringBuilder();
    537     if ((flags & Display.FLAG_SECURE) != 0) {
    538       result.append(", FLAG_SECURE");
    539     }
    540     if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
    541       result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
    542     }
    543     if ((flags & Display.FLAG_PRIVATE) != 0) {
    544       result.append(", FLAG_PRIVATE");
    545     }
    546     if ((flags & Display.FLAG_PRESENTATION) != 0) {
    547       result.append(", FLAG_PRESENTATION");
    548     }
    549     if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
    550       result.append(", FLAG_SCALING_DISABLED");
    551     }
    552     if ((flags & Display.FLAG_ROUND) != 0) {
    553       result.append(", FLAG_ROUND");
    554     }
    555     return result.toString();
    556   }
    557 }
    558