Home | History | Annotate | Download | only in view
      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 android.view;
     18 
     19 import android.content.res.CompatibilityInfo;
     20 import android.content.res.Configuration;
     21 import android.os.Parcel;
     22 import android.os.Parcelable;
     23 import android.util.ArraySet;
     24 import android.util.DisplayMetrics;
     25 
     26 import java.util.Arrays;
     27 
     28 import libcore.util.Objects;
     29 
     30 /**
     31  * Describes the characteristics of a particular logical display.
     32  * @hide
     33  */
     34 public final class DisplayInfo implements Parcelable {
     35     /**
     36      * The surface flinger layer stack associated with this logical display.
     37      */
     38     public int layerStack;
     39 
     40     /**
     41      * Display flags.
     42      */
     43     public int flags;
     44 
     45     /**
     46      * Display type.
     47      */
     48     public int type;
     49 
     50     /**
     51      * Display address, or null if none.
     52      * Interpretation varies by display type.
     53      */
     54     public String address;
     55 
     56     /**
     57      * The human-readable name of the display.
     58      */
     59     public String name;
     60 
     61     /**
     62      * Unique identifier for the display. Shouldn't be displayed to the user.
     63      */
     64     public String uniqueId;
     65 
     66     /**
     67      * The width of the portion of the display that is available to applications, in pixels.
     68      * Represents the size of the display minus any system decorations.
     69      */
     70     public int appWidth;
     71 
     72     /**
     73      * The height of the portion of the display that is available to applications, in pixels.
     74      * Represents the size of the display minus any system decorations.
     75      */
     76     public int appHeight;
     77 
     78     /**
     79      * The smallest value of {@link #appWidth} that an application is likely to encounter,
     80      * in pixels, excepting cases where the width may be even smaller due to the presence
     81      * of a soft keyboard, for example.
     82      */
     83     public int smallestNominalAppWidth;
     84 
     85     /**
     86      * The smallest value of {@link #appHeight} that an application is likely to encounter,
     87      * in pixels, excepting cases where the height may be even smaller due to the presence
     88      * of a soft keyboard, for example.
     89      */
     90     public int smallestNominalAppHeight;
     91 
     92     /**
     93      * The largest value of {@link #appWidth} that an application is likely to encounter,
     94      * in pixels, excepting cases where the width may be even larger due to system decorations
     95      * such as the status bar being hidden, for example.
     96      */
     97     public int largestNominalAppWidth;
     98 
     99     /**
    100      * The largest value of {@link #appHeight} that an application is likely to encounter,
    101      * in pixels, excepting cases where the height may be even larger due to system decorations
    102      * such as the status bar being hidden, for example.
    103      */
    104     public int largestNominalAppHeight;
    105 
    106     /**
    107      * The logical width of the display, in pixels.
    108      * Represents the usable size of the display which may be smaller than the
    109      * physical size when the system is emulating a smaller display.
    110      */
    111     public int logicalWidth;
    112 
    113     /**
    114      * The logical height 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 logicalHeight;
    119 
    120     /**
    121      * @hide
    122      * Number of overscan pixels on the left side of the display.
    123      */
    124     public int overscanLeft;
    125 
    126     /**
    127      * @hide
    128      * Number of overscan pixels on the top side of the display.
    129      */
    130     public int overscanTop;
    131 
    132     /**
    133      * @hide
    134      * Number of overscan pixels on the right side of the display.
    135      */
    136     public int overscanRight;
    137 
    138     /**
    139      * @hide
    140      * Number of overscan pixels on the bottom side of the display.
    141      */
    142     public int overscanBottom;
    143 
    144     /**
    145      * The rotation of the display relative to its natural orientation.
    146      * May be one of {@link android.view.Surface#ROTATION_0},
    147      * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
    148      * {@link android.view.Surface#ROTATION_270}.
    149      * <p>
    150      * The value of this field is indeterminate if the logical display is presented on
    151      * more than one physical display.
    152      * </p>
    153      */
    154     @Surface.Rotation
    155     public int rotation;
    156 
    157     /**
    158      * The active display mode.
    159      */
    160     public int modeId;
    161 
    162     /**
    163      * The default display mode.
    164      */
    165     public int defaultModeId;
    166 
    167     /**
    168      * The supported modes of this display.
    169      */
    170     public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
    171 
    172     /** The active color mode. */
    173     public int colorMode;
    174 
    175     /** The list of supported color modes */
    176     public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
    177 
    178     /** The display's HDR capabilities */
    179     public Display.HdrCapabilities hdrCapabilities;
    180 
    181     /**
    182      * The logical display density which is the basis for density-independent
    183      * pixels.
    184      */
    185     public int logicalDensityDpi;
    186 
    187     /**
    188      * The exact physical pixels per inch of the screen in the X dimension.
    189      * <p>
    190      * The value of this field is indeterminate if the logical display is presented on
    191      * more than one physical display.
    192      * </p>
    193      */
    194     public float physicalXDpi;
    195 
    196     /**
    197      * The exact physical pixels per inch of the screen in the Y dimension.
    198      * <p>
    199      * The value of this field is indeterminate if the logical display is presented on
    200      * more than one physical display.
    201      * </p>
    202      */
    203     public float physicalYDpi;
    204 
    205     /**
    206      * This is a positive value indicating the phase offset of the VSYNC events provided by
    207      * Choreographer relative to the display refresh.  For example, if Choreographer reports
    208      * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
    209      */
    210     public long appVsyncOffsetNanos;
    211 
    212     /**
    213      * This is how far in advance a buffer must be queued for presentation at
    214      * a given time.  If you want a buffer to appear on the screen at
    215      * time N, you must submit the buffer before (N - bufferDeadlineNanos).
    216      */
    217     public long presentationDeadlineNanos;
    218 
    219     /**
    220      * The state of the display, such as {@link android.view.Display#STATE_ON}.
    221      */
    222     public int state;
    223 
    224     /**
    225      * The UID of the application that owns this display, or zero if it is owned by the system.
    226      * <p>
    227      * If the display is private, then only the owner can use it.
    228      * </p>
    229      */
    230     public int ownerUid;
    231 
    232     /**
    233      * The package name of the application that owns this display, or null if it is
    234      * owned by the system.
    235      * <p>
    236      * If the display is private, then only the owner can use it.
    237      * </p>
    238      */
    239     public String ownerPackageName;
    240 
    241     public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
    242         @Override
    243         public DisplayInfo createFromParcel(Parcel source) {
    244             return new DisplayInfo(source);
    245         }
    246 
    247         @Override
    248         public DisplayInfo[] newArray(int size) {
    249             return new DisplayInfo[size];
    250         }
    251     };
    252 
    253     public DisplayInfo() {
    254     }
    255 
    256     public DisplayInfo(DisplayInfo other) {
    257         copyFrom(other);
    258     }
    259 
    260     private DisplayInfo(Parcel source) {
    261         readFromParcel(source);
    262     }
    263 
    264     @Override
    265     public boolean equals(Object o) {
    266         return o instanceof DisplayInfo && equals((DisplayInfo)o);
    267     }
    268 
    269     public boolean equals(DisplayInfo other) {
    270         return other != null
    271                 && layerStack == other.layerStack
    272                 && flags == other.flags
    273                 && type == other.type
    274                 && Objects.equal(address, other.address)
    275                 && Objects.equal(uniqueId, other.uniqueId)
    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                 && overscanLeft == other.overscanLeft
    285                 && overscanTop == other.overscanTop
    286                 && overscanRight == other.overscanRight
    287                 && overscanBottom == other.overscanBottom
    288                 && rotation == other.rotation
    289                 && modeId == other.modeId
    290                 && defaultModeId == other.defaultModeId
    291                 && colorMode == other.colorMode
    292                 && Arrays.equals(supportedColorModes, other.supportedColorModes)
    293                 && Objects.equal(hdrCapabilities, other.hdrCapabilities)
    294                 && logicalDensityDpi == other.logicalDensityDpi
    295                 && physicalXDpi == other.physicalXDpi
    296                 && physicalYDpi == other.physicalYDpi
    297                 && appVsyncOffsetNanos == other.appVsyncOffsetNanos
    298                 && presentationDeadlineNanos == other.presentationDeadlineNanos
    299                 && state == other.state
    300                 && ownerUid == other.ownerUid
    301                 && Objects.equal(ownerPackageName, other.ownerPackageName);
    302     }
    303 
    304     @Override
    305     public int hashCode() {
    306         return 0; // don't care
    307     }
    308 
    309     public void copyFrom(DisplayInfo other) {
    310         layerStack = other.layerStack;
    311         flags = other.flags;
    312         type = other.type;
    313         address = other.address;
    314         name = other.name;
    315         uniqueId = other.uniqueId;
    316         appWidth = other.appWidth;
    317         appHeight = other.appHeight;
    318         smallestNominalAppWidth = other.smallestNominalAppWidth;
    319         smallestNominalAppHeight = other.smallestNominalAppHeight;
    320         largestNominalAppWidth = other.largestNominalAppWidth;
    321         largestNominalAppHeight = other.largestNominalAppHeight;
    322         logicalWidth = other.logicalWidth;
    323         logicalHeight = other.logicalHeight;
    324         overscanLeft = other.overscanLeft;
    325         overscanTop = other.overscanTop;
    326         overscanRight = other.overscanRight;
    327         overscanBottom = other.overscanBottom;
    328         rotation = other.rotation;
    329         modeId = other.modeId;
    330         defaultModeId = other.defaultModeId;
    331         supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
    332         colorMode = other.colorMode;
    333         supportedColorModes = Arrays.copyOf(
    334                 other.supportedColorModes, other.supportedColorModes.length);
    335         hdrCapabilities = other.hdrCapabilities;
    336         logicalDensityDpi = other.logicalDensityDpi;
    337         physicalXDpi = other.physicalXDpi;
    338         physicalYDpi = other.physicalYDpi;
    339         appVsyncOffsetNanos = other.appVsyncOffsetNanos;
    340         presentationDeadlineNanos = other.presentationDeadlineNanos;
    341         state = other.state;
    342         ownerUid = other.ownerUid;
    343         ownerPackageName = other.ownerPackageName;
    344     }
    345 
    346     public void readFromParcel(Parcel source) {
    347         layerStack = source.readInt();
    348         flags = source.readInt();
    349         type = source.readInt();
    350         address = source.readString();
    351         name = source.readString();
    352         appWidth = source.readInt();
    353         appHeight = source.readInt();
    354         smallestNominalAppWidth = source.readInt();
    355         smallestNominalAppHeight = source.readInt();
    356         largestNominalAppWidth = source.readInt();
    357         largestNominalAppHeight = source.readInt();
    358         logicalWidth = source.readInt();
    359         logicalHeight = source.readInt();
    360         overscanLeft = source.readInt();
    361         overscanTop = source.readInt();
    362         overscanRight = source.readInt();
    363         overscanBottom = source.readInt();
    364         rotation = source.readInt();
    365         modeId = source.readInt();
    366         defaultModeId = source.readInt();
    367         int nModes = source.readInt();
    368         supportedModes = new Display.Mode[nModes];
    369         for (int i = 0; i < nModes; i++) {
    370             supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
    371         }
    372         colorMode = source.readInt();
    373         int nColorModes = source.readInt();
    374         supportedColorModes = new int[nColorModes];
    375         for (int i = 0; i < nColorModes; i++) {
    376             supportedColorModes[i] = source.readInt();
    377         }
    378         hdrCapabilities = source.readParcelable(null);
    379         logicalDensityDpi = source.readInt();
    380         physicalXDpi = source.readFloat();
    381         physicalYDpi = source.readFloat();
    382         appVsyncOffsetNanos = source.readLong();
    383         presentationDeadlineNanos = source.readLong();
    384         state = source.readInt();
    385         ownerUid = source.readInt();
    386         ownerPackageName = source.readString();
    387         uniqueId = source.readString();
    388     }
    389 
    390     @Override
    391     public void writeToParcel(Parcel dest, int flags) {
    392         dest.writeInt(layerStack);
    393         dest.writeInt(this.flags);
    394         dest.writeInt(type);
    395         dest.writeString(address);
    396         dest.writeString(name);
    397         dest.writeInt(appWidth);
    398         dest.writeInt(appHeight);
    399         dest.writeInt(smallestNominalAppWidth);
    400         dest.writeInt(smallestNominalAppHeight);
    401         dest.writeInt(largestNominalAppWidth);
    402         dest.writeInt(largestNominalAppHeight);
    403         dest.writeInt(logicalWidth);
    404         dest.writeInt(logicalHeight);
    405         dest.writeInt(overscanLeft);
    406         dest.writeInt(overscanTop);
    407         dest.writeInt(overscanRight);
    408         dest.writeInt(overscanBottom);
    409         dest.writeInt(rotation);
    410         dest.writeInt(modeId);
    411         dest.writeInt(defaultModeId);
    412         dest.writeInt(supportedModes.length);
    413         for (int i = 0; i < supportedModes.length; i++) {
    414             supportedModes[i].writeToParcel(dest, flags);
    415         }
    416         dest.writeInt(colorMode);
    417         dest.writeInt(supportedColorModes.length);
    418         for (int i = 0; i < supportedColorModes.length; i++) {
    419             dest.writeInt(supportedColorModes[i]);
    420         }
    421         dest.writeParcelable(hdrCapabilities, flags);
    422         dest.writeInt(logicalDensityDpi);
    423         dest.writeFloat(physicalXDpi);
    424         dest.writeFloat(physicalYDpi);
    425         dest.writeLong(appVsyncOffsetNanos);
    426         dest.writeLong(presentationDeadlineNanos);
    427         dest.writeInt(state);
    428         dest.writeInt(ownerUid);
    429         dest.writeString(ownerPackageName);
    430         dest.writeString(uniqueId);
    431     }
    432 
    433     @Override
    434     public int describeContents() {
    435         return 0;
    436     }
    437 
    438     public Display.Mode getMode() {
    439         return findMode(modeId);
    440     }
    441 
    442     public Display.Mode getDefaultMode() {
    443         return findMode(defaultModeId);
    444     }
    445 
    446     private Display.Mode findMode(int id) {
    447         for (int i = 0; i < supportedModes.length; i++) {
    448             if (supportedModes[i].getModeId() == id) {
    449                 return supportedModes[i];
    450             }
    451         }
    452         throw new IllegalStateException("Unable to locate mode " + id);
    453     }
    454 
    455     /**
    456      * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable
    457      * mode could be found.
    458      */
    459     public int findDefaultModeByRefreshRate(float refreshRate) {
    460         Display.Mode[] modes = supportedModes;
    461         Display.Mode defaultMode = getDefaultMode();
    462         for (int i = 0; i < modes.length; i++) {
    463             if (modes[i].matches(
    464                     defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) {
    465                 return modes[i].getModeId();
    466             }
    467         }
    468         return 0;
    469     }
    470 
    471     /**
    472      * Returns the list of supported refresh rates in the default mode.
    473      */
    474     public float[] getDefaultRefreshRates() {
    475         Display.Mode[] modes = supportedModes;
    476         ArraySet<Float> rates = new ArraySet<>();
    477         Display.Mode defaultMode = getDefaultMode();
    478         for (int i = 0; i < modes.length; i++) {
    479             Display.Mode mode = modes[i];
    480             if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth()
    481                     && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) {
    482                 rates.add(mode.getRefreshRate());
    483             }
    484         }
    485         float[] result = new float[rates.size()];
    486         int i = 0;
    487         for (Float rate : rates) {
    488             result[i++] = rate;
    489         }
    490         return result;
    491     }
    492 
    493     public void getAppMetrics(DisplayMetrics outMetrics) {
    494         getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
    495     }
    496 
    497     public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
    498         getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
    499                 displayAdjustments.getConfiguration(), appWidth, appHeight);
    500     }
    501 
    502     public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci,
    503             Configuration configuration) {
    504         getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
    505     }
    506 
    507     public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
    508             Configuration configuration) {
    509         getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
    510     }
    511 
    512     public int getNaturalWidth() {
    513         return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
    514                 logicalWidth : logicalHeight;
    515     }
    516 
    517     public int getNaturalHeight() {
    518         return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
    519                 logicalHeight : logicalWidth;
    520     }
    521 
    522     /**
    523      * Returns true if the specified UID has access to this display.
    524      */
    525     public boolean hasAccess(int uid) {
    526         return Display.hasAccess(uid, flags, ownerUid);
    527     }
    528 
    529     private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
    530             Configuration configuration, int width, int height) {
    531         outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
    532         outMetrics.density = outMetrics.noncompatDensity =
    533                 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
    534         outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
    535         outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
    536         outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
    537 
    538         width = (configuration != null
    539                 && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED)
    540                 ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width;
    541         height = (configuration != null
    542                 && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED)
    543                 ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height;
    544 
    545         outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
    546         outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
    547 
    548         if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
    549             compatInfo.applyToDisplayMetrics(outMetrics);
    550         }
    551     }
    552 
    553     // For debugging purposes
    554     @Override
    555     public String toString() {
    556         StringBuilder sb = new StringBuilder();
    557         sb.append("DisplayInfo{\"");
    558         sb.append(name);
    559         sb.append("\", uniqueId \"");
    560         sb.append(uniqueId);
    561         sb.append("\", app ");
    562         sb.append(appWidth);
    563         sb.append(" x ");
    564         sb.append(appHeight);
    565         sb.append(", real ");
    566         sb.append(logicalWidth);
    567         sb.append(" x ");
    568         sb.append(logicalHeight);
    569         if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) {
    570             sb.append(", overscan (");
    571             sb.append(overscanLeft);
    572             sb.append(",");
    573             sb.append(overscanTop);
    574             sb.append(",");
    575             sb.append(overscanRight);
    576             sb.append(",");
    577             sb.append(overscanBottom);
    578             sb.append(")");
    579         }
    580         sb.append(", largest app ");
    581         sb.append(largestNominalAppWidth);
    582         sb.append(" x ");
    583         sb.append(largestNominalAppHeight);
    584         sb.append(", smallest app ");
    585         sb.append(smallestNominalAppWidth);
    586         sb.append(" x ");
    587         sb.append(smallestNominalAppHeight);
    588         sb.append(", mode ");
    589         sb.append(modeId);
    590         sb.append(", defaultMode ");
    591         sb.append(defaultModeId);
    592         sb.append(", modes ");
    593         sb.append(Arrays.toString(supportedModes));
    594         sb.append(", colorMode ");
    595         sb.append(colorMode);
    596         sb.append(", supportedColorModes ");
    597         sb.append(Arrays.toString(supportedColorModes));
    598         sb.append(", hdrCapabilities ");
    599         sb.append(hdrCapabilities);
    600         sb.append(", rotation ");
    601         sb.append(rotation);
    602         sb.append(", density ");
    603         sb.append(logicalDensityDpi);
    604         sb.append(" (");
    605         sb.append(physicalXDpi);
    606         sb.append(" x ");
    607         sb.append(physicalYDpi);
    608         sb.append(") dpi, layerStack ");
    609         sb.append(layerStack);
    610         sb.append(", appVsyncOff ");
    611         sb.append(appVsyncOffsetNanos);
    612         sb.append(", presDeadline ");
    613         sb.append(presentationDeadlineNanos);
    614         sb.append(", type ");
    615         sb.append(Display.typeToString(type));
    616         if (address != null) {
    617             sb.append(", address ").append(address);
    618         }
    619         sb.append(", state ");
    620         sb.append(Display.stateToString(state));
    621         if (ownerUid != 0 || ownerPackageName != null) {
    622             sb.append(", owner ").append(ownerPackageName);
    623             sb.append(" (uid ").append(ownerUid).append(")");
    624         }
    625         sb.append(flagsToString(flags));
    626         sb.append("}");
    627         return sb.toString();
    628     }
    629 
    630     private static String flagsToString(int flags) {
    631         StringBuilder result = new StringBuilder();
    632         if ((flags & Display.FLAG_SECURE) != 0) {
    633             result.append(", FLAG_SECURE");
    634         }
    635         if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
    636             result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
    637         }
    638         if ((flags & Display.FLAG_PRIVATE) != 0) {
    639             result.append(", FLAG_PRIVATE");
    640         }
    641         if ((flags & Display.FLAG_PRESENTATION) != 0) {
    642             result.append(", FLAG_PRESENTATION");
    643         }
    644         if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
    645             result.append(", FLAG_SCALING_DISABLED");
    646         }
    647         if ((flags & Display.FLAG_ROUND) != 0) {
    648             result.append(", FLAG_ROUND");
    649         }
    650         return result.toString();
    651     }
    652 }
    653