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     /**
    173      * The logical display density which is the basis for density-independent
    174      * pixels.
    175      */
    176     public int logicalDensityDpi;
    177 
    178     /**
    179      * The exact physical pixels per inch of the screen in the X dimension.
    180      * <p>
    181      * The value of this field is indeterminate if the logical display is presented on
    182      * more than one physical display.
    183      * </p>
    184      */
    185     public float physicalXDpi;
    186 
    187     /**
    188      * The exact physical pixels per inch of the screen in the Y 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 physicalYDpi;
    195 
    196     /**
    197      * This is a positive value indicating the phase offset of the VSYNC events provided by
    198      * Choreographer relative to the display refresh.  For example, if Choreographer reports
    199      * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
    200      */
    201     public long appVsyncOffsetNanos;
    202 
    203     /**
    204      * This is how far in advance a buffer must be queued for presentation at
    205      * a given time.  If you want a buffer to appear on the screen at
    206      * time N, you must submit the buffer before (N - bufferDeadlineNanos).
    207      */
    208     public long presentationDeadlineNanos;
    209 
    210     /**
    211      * The state of the display, such as {@link android.view.Display#STATE_ON}.
    212      */
    213     public int state;
    214 
    215     /**
    216      * The UID of the application that owns this display, or zero if it is owned by the system.
    217      * <p>
    218      * If the display is private, then only the owner can use it.
    219      * </p>
    220      */
    221     public int ownerUid;
    222 
    223     /**
    224      * The package name of the application that owns this display, or null if it is
    225      * owned by the system.
    226      * <p>
    227      * If the display is private, then only the owner can use it.
    228      * </p>
    229      */
    230     public String ownerPackageName;
    231 
    232     public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
    233         @Override
    234         public DisplayInfo createFromParcel(Parcel source) {
    235             return new DisplayInfo(source);
    236         }
    237 
    238         @Override
    239         public DisplayInfo[] newArray(int size) {
    240             return new DisplayInfo[size];
    241         }
    242     };
    243 
    244     public DisplayInfo() {
    245     }
    246 
    247     public DisplayInfo(DisplayInfo other) {
    248         copyFrom(other);
    249     }
    250 
    251     private DisplayInfo(Parcel source) {
    252         readFromParcel(source);
    253     }
    254 
    255     @Override
    256     public boolean equals(Object o) {
    257         return o instanceof DisplayInfo && equals((DisplayInfo)o);
    258     }
    259 
    260     public boolean equals(DisplayInfo other) {
    261         return other != null
    262                 && layerStack == other.layerStack
    263                 && flags == other.flags
    264                 && type == other.type
    265                 && Objects.equal(address, other.address)
    266                 && Objects.equal(uniqueId, other.uniqueId)
    267                 && appWidth == other.appWidth
    268                 && appHeight == other.appHeight
    269                 && smallestNominalAppWidth == other.smallestNominalAppWidth
    270                 && smallestNominalAppHeight == other.smallestNominalAppHeight
    271                 && largestNominalAppWidth == other.largestNominalAppWidth
    272                 && largestNominalAppHeight == other.largestNominalAppHeight
    273                 && logicalWidth == other.logicalWidth
    274                 && logicalHeight == other.logicalHeight
    275                 && overscanLeft == other.overscanLeft
    276                 && overscanTop == other.overscanTop
    277                 && overscanRight == other.overscanRight
    278                 && overscanBottom == other.overscanBottom
    279                 && rotation == other.rotation
    280                 && modeId == other.modeId
    281                 && defaultModeId == other.defaultModeId
    282                 && logicalDensityDpi == other.logicalDensityDpi
    283                 && physicalXDpi == other.physicalXDpi
    284                 && physicalYDpi == other.physicalYDpi
    285                 && appVsyncOffsetNanos == other.appVsyncOffsetNanos
    286                 && presentationDeadlineNanos == other.presentationDeadlineNanos
    287                 && state == other.state
    288                 && ownerUid == other.ownerUid
    289                 && Objects.equal(ownerPackageName, other.ownerPackageName);
    290     }
    291 
    292     @Override
    293     public int hashCode() {
    294         return 0; // don't care
    295     }
    296 
    297     public void copyFrom(DisplayInfo other) {
    298         layerStack = other.layerStack;
    299         flags = other.flags;
    300         type = other.type;
    301         address = other.address;
    302         name = other.name;
    303         uniqueId = other.uniqueId;
    304         appWidth = other.appWidth;
    305         appHeight = other.appHeight;
    306         smallestNominalAppWidth = other.smallestNominalAppWidth;
    307         smallestNominalAppHeight = other.smallestNominalAppHeight;
    308         largestNominalAppWidth = other.largestNominalAppWidth;
    309         largestNominalAppHeight = other.largestNominalAppHeight;
    310         logicalWidth = other.logicalWidth;
    311         logicalHeight = other.logicalHeight;
    312         overscanLeft = other.overscanLeft;
    313         overscanTop = other.overscanTop;
    314         overscanRight = other.overscanRight;
    315         overscanBottom = other.overscanBottom;
    316         rotation = other.rotation;
    317         modeId = other.modeId;
    318         defaultModeId = other.defaultModeId;
    319         supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
    320         logicalDensityDpi = other.logicalDensityDpi;
    321         physicalXDpi = other.physicalXDpi;
    322         physicalYDpi = other.physicalYDpi;
    323         appVsyncOffsetNanos = other.appVsyncOffsetNanos;
    324         presentationDeadlineNanos = other.presentationDeadlineNanos;
    325         state = other.state;
    326         ownerUid = other.ownerUid;
    327         ownerPackageName = other.ownerPackageName;
    328     }
    329 
    330     public void readFromParcel(Parcel source) {
    331         layerStack = source.readInt();
    332         flags = source.readInt();
    333         type = source.readInt();
    334         address = source.readString();
    335         name = source.readString();
    336         appWidth = source.readInt();
    337         appHeight = source.readInt();
    338         smallestNominalAppWidth = source.readInt();
    339         smallestNominalAppHeight = source.readInt();
    340         largestNominalAppWidth = source.readInt();
    341         largestNominalAppHeight = source.readInt();
    342         logicalWidth = source.readInt();
    343         logicalHeight = source.readInt();
    344         overscanLeft = source.readInt();
    345         overscanTop = source.readInt();
    346         overscanRight = source.readInt();
    347         overscanBottom = source.readInt();
    348         rotation = source.readInt();
    349         modeId = source.readInt();
    350         defaultModeId = source.readInt();
    351         int nModes = source.readInt();
    352         supportedModes = new Display.Mode[nModes];
    353         for (int i = 0; i < nModes; i++) {
    354             supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
    355         }
    356         logicalDensityDpi = source.readInt();
    357         physicalXDpi = source.readFloat();
    358         physicalYDpi = source.readFloat();
    359         appVsyncOffsetNanos = source.readLong();
    360         presentationDeadlineNanos = source.readLong();
    361         state = source.readInt();
    362         ownerUid = source.readInt();
    363         ownerPackageName = source.readString();
    364         uniqueId = source.readString();
    365     }
    366 
    367     @Override
    368     public void writeToParcel(Parcel dest, int flags) {
    369         dest.writeInt(layerStack);
    370         dest.writeInt(this.flags);
    371         dest.writeInt(type);
    372         dest.writeString(address);
    373         dest.writeString(name);
    374         dest.writeInt(appWidth);
    375         dest.writeInt(appHeight);
    376         dest.writeInt(smallestNominalAppWidth);
    377         dest.writeInt(smallestNominalAppHeight);
    378         dest.writeInt(largestNominalAppWidth);
    379         dest.writeInt(largestNominalAppHeight);
    380         dest.writeInt(logicalWidth);
    381         dest.writeInt(logicalHeight);
    382         dest.writeInt(overscanLeft);
    383         dest.writeInt(overscanTop);
    384         dest.writeInt(overscanRight);
    385         dest.writeInt(overscanBottom);
    386         dest.writeInt(rotation);
    387         dest.writeInt(modeId);
    388         dest.writeInt(defaultModeId);
    389         dest.writeInt(supportedModes.length);
    390         for (int i = 0; i < supportedModes.length; i++) {
    391             supportedModes[i].writeToParcel(dest, flags);
    392         }
    393         dest.writeInt(logicalDensityDpi);
    394         dest.writeFloat(physicalXDpi);
    395         dest.writeFloat(physicalYDpi);
    396         dest.writeLong(appVsyncOffsetNanos);
    397         dest.writeLong(presentationDeadlineNanos);
    398         dest.writeInt(state);
    399         dest.writeInt(ownerUid);
    400         dest.writeString(ownerPackageName);
    401         dest.writeString(uniqueId);
    402     }
    403 
    404     @Override
    405     public int describeContents() {
    406         return 0;
    407     }
    408 
    409     public Display.Mode getMode() {
    410         return findMode(modeId);
    411     }
    412 
    413     public Display.Mode getDefaultMode() {
    414         return findMode(defaultModeId);
    415     }
    416 
    417     private Display.Mode findMode(int id) {
    418         for (int i = 0; i < supportedModes.length; i++) {
    419             if (supportedModes[i].getModeId() == id) {
    420                 return supportedModes[i];
    421             }
    422         }
    423         throw new IllegalStateException("Unable to locate mode " + id);
    424     }
    425 
    426     /**
    427      * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable
    428      * mode could be found.
    429      */
    430     public int findDefaultModeByRefreshRate(float refreshRate) {
    431         Display.Mode[] modes = supportedModes;
    432         Display.Mode defaultMode = getDefaultMode();
    433         for (int i = 0; i < modes.length; i++) {
    434             if (modes[i].matches(
    435                     defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) {
    436                 return modes[i].getModeId();
    437             }
    438         }
    439         return 0;
    440     }
    441 
    442     /**
    443      * Returns the list of supported refresh rates in the default mode.
    444      */
    445     public float[] getDefaultRefreshRates() {
    446         Display.Mode[] modes = supportedModes;
    447         ArraySet<Float> rates = new ArraySet<>();
    448         Display.Mode defaultMode = getDefaultMode();
    449         for (int i = 0; i < modes.length; i++) {
    450             Display.Mode mode = modes[i];
    451             if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth()
    452                     && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) {
    453                 rates.add(mode.getRefreshRate());
    454             }
    455         }
    456         float[] result = new float[rates.size()];
    457         int i = 0;
    458         for (Float rate : rates) {
    459             result[i++] = rate;
    460         }
    461         return result;
    462     }
    463 
    464     public void getAppMetrics(DisplayMetrics outMetrics) {
    465         getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
    466     }
    467 
    468     public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
    469         getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
    470                 displayAdjustments.getConfiguration(), appWidth, appHeight);
    471     }
    472 
    473     public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci,
    474             Configuration configuration) {
    475         getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
    476     }
    477 
    478     public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
    479             Configuration configuration) {
    480         getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
    481     }
    482 
    483     public int getNaturalWidth() {
    484         return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
    485                 logicalWidth : logicalHeight;
    486     }
    487 
    488     public int getNaturalHeight() {
    489         return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
    490                 logicalHeight : logicalWidth;
    491     }
    492 
    493     /**
    494      * Returns true if the specified UID has access to this display.
    495      */
    496     public boolean hasAccess(int uid) {
    497         return Display.hasAccess(uid, flags, ownerUid);
    498     }
    499 
    500     private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
    501             Configuration configuration, int width, int height) {
    502         outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
    503         outMetrics.density = outMetrics.noncompatDensity =
    504                 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
    505         outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
    506         outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
    507         outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
    508 
    509         width = (configuration != null
    510                 && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED)
    511                 ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width;
    512         height = (configuration != null
    513                 && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED)
    514                 ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height;
    515 
    516         outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
    517         outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
    518 
    519         if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
    520             compatInfo.applyToDisplayMetrics(outMetrics);
    521         }
    522     }
    523 
    524     // For debugging purposes
    525     @Override
    526     public String toString() {
    527         StringBuilder sb = new StringBuilder();
    528         sb.append("DisplayInfo{\"");
    529         sb.append(name);
    530         sb.append("\", uniqueId \"");
    531         sb.append(uniqueId);
    532         sb.append("\", app ");
    533         sb.append(appWidth);
    534         sb.append(" x ");
    535         sb.append(appHeight);
    536         sb.append(", real ");
    537         sb.append(logicalWidth);
    538         sb.append(" x ");
    539         sb.append(logicalHeight);
    540         if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) {
    541             sb.append(", overscan (");
    542             sb.append(overscanLeft);
    543             sb.append(",");
    544             sb.append(overscanTop);
    545             sb.append(",");
    546             sb.append(overscanRight);
    547             sb.append(",");
    548             sb.append(overscanBottom);
    549             sb.append(")");
    550         }
    551         sb.append(", largest app ");
    552         sb.append(largestNominalAppWidth);
    553         sb.append(" x ");
    554         sb.append(largestNominalAppHeight);
    555         sb.append(", smallest app ");
    556         sb.append(smallestNominalAppWidth);
    557         sb.append(" x ");
    558         sb.append(smallestNominalAppHeight);
    559         sb.append(", mode ");
    560         sb.append(modeId);
    561         sb.append(", defaultMode ");
    562         sb.append(defaultModeId);
    563         sb.append(", modes ");
    564         sb.append(Arrays.toString(supportedModes));
    565         sb.append(", rotation ");
    566         sb.append(rotation);
    567         sb.append(", density ");
    568         sb.append(logicalDensityDpi);
    569         sb.append(" (");
    570         sb.append(physicalXDpi);
    571         sb.append(" x ");
    572         sb.append(physicalYDpi);
    573         sb.append(") dpi, layerStack ");
    574         sb.append(layerStack);
    575         sb.append(", appVsyncOff ");
    576         sb.append(appVsyncOffsetNanos);
    577         sb.append(", presDeadline ");
    578         sb.append(presentationDeadlineNanos);
    579         sb.append(", type ");
    580         sb.append(Display.typeToString(type));
    581         if (address != null) {
    582             sb.append(", address ").append(address);
    583         }
    584         sb.append(", state ");
    585         sb.append(Display.stateToString(state));
    586         if (ownerUid != 0 || ownerPackageName != null) {
    587             sb.append(", owner ").append(ownerPackageName);
    588             sb.append(" (uid ").append(ownerUid).append(")");
    589         }
    590         sb.append(flagsToString(flags));
    591         sb.append("}");
    592         return sb.toString();
    593     }
    594 
    595     private static String flagsToString(int flags) {
    596         StringBuilder result = new StringBuilder();
    597         if ((flags & Display.FLAG_SECURE) != 0) {
    598             result.append(", FLAG_SECURE");
    599         }
    600         if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
    601             result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
    602         }
    603         if ((flags & Display.FLAG_PRIVATE) != 0) {
    604             result.append(", FLAG_PRIVATE");
    605         }
    606         if ((flags & Display.FLAG_PRESENTATION) != 0) {
    607             result.append(", FLAG_PRESENTATION");
    608         }
    609         if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
    610             result.append(", FLAG_SCALING_DISABLED");
    611         }
    612         if ((flags & Display.FLAG_ROUND) != 0) {
    613             result.append(", FLAG_ROUND");
    614         }
    615         return result.toString();
    616     }
    617 }
    618