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