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.os.Parcel; 21 import android.os.Parcelable; 22 import android.util.DisplayMetrics; 23 24 import libcore.util.Objects; 25 26 /** 27 * Describes the characteristics of a particular logical display. 28 * @hide 29 */ 30 public final class DisplayInfo implements Parcelable { 31 /** 32 * The surface flinger layer stack associated with this logical display. 33 */ 34 public int layerStack; 35 36 /** 37 * Display flags. 38 */ 39 public int flags; 40 41 /** 42 * Display type. 43 */ 44 public int type; 45 46 /** 47 * Display address, or null if none. 48 * Interpretation varies by display type. 49 */ 50 public String address; 51 52 /** 53 * The human-readable name of the display. 54 */ 55 public String name; 56 57 /** 58 * The width of the portion of the display that is available to applications, in pixels. 59 * Represents the size of the display minus any system decorations. 60 */ 61 public int appWidth; 62 63 /** 64 * The height of the portion of the display that is available to applications, in pixels. 65 * Represents the size of the display minus any system decorations. 66 */ 67 public int appHeight; 68 69 /** 70 * The smallest value of {@link #appWidth} that an application is likely to encounter, 71 * in pixels, excepting cases where the width may be even smaller due to the presence 72 * of a soft keyboard, for example. 73 */ 74 public int smallestNominalAppWidth; 75 76 /** 77 * The smallest value of {@link #appHeight} that an application is likely to encounter, 78 * in pixels, excepting cases where the height may be even smaller due to the presence 79 * of a soft keyboard, for example. 80 */ 81 public int smallestNominalAppHeight; 82 83 /** 84 * The largest value of {@link #appWidth} that an application is likely to encounter, 85 * in pixels, excepting cases where the width may be even larger due to system decorations 86 * such as the status bar being hidden, for example. 87 */ 88 public int largestNominalAppWidth; 89 90 /** 91 * The largest value of {@link #appHeight} that an application is likely to encounter, 92 * in pixels, excepting cases where the height may be even larger due to system decorations 93 * such as the status bar being hidden, for example. 94 */ 95 public int largestNominalAppHeight; 96 97 /** 98 * The logical width of the display, in pixels. 99 * Represents the usable size of the display which may be smaller than the 100 * physical size when the system is emulating a smaller display. 101 */ 102 public int logicalWidth; 103 104 /** 105 * The logical height of the display, in pixels. 106 * Represents the usable size of the display which may be smaller than the 107 * physical size when the system is emulating a smaller display. 108 */ 109 public int logicalHeight; 110 111 /** 112 * @hide 113 * Number of overscan pixels on the left side of the display. 114 */ 115 public int overscanLeft; 116 117 /** 118 * @hide 119 * Number of overscan pixels on the top side of the display. 120 */ 121 public int overscanTop; 122 123 /** 124 * @hide 125 * Number of overscan pixels on the right side of the display. 126 */ 127 public int overscanRight; 128 129 /** 130 * @hide 131 * Number of overscan pixels on the bottom side of the display. 132 */ 133 public int overscanBottom; 134 135 /** 136 * The rotation of the display relative to its natural orientation. 137 * May be one of {@link android.view.Surface#ROTATION_0}, 138 * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180}, 139 * {@link android.view.Surface#ROTATION_270}. 140 * <p> 141 * The value of this field is indeterminate if the logical display is presented on 142 * more than one physical display. 143 * </p> 144 */ 145 public int rotation; 146 147 /** 148 * The refresh rate of this display in frames per second. 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 public float refreshRate; 155 156 /** 157 * The logical display density which is the basis for density-independent 158 * pixels. 159 */ 160 public int logicalDensityDpi; 161 162 /** 163 * The exact physical pixels per inch of the screen in the X dimension. 164 * <p> 165 * The value of this field is indeterminate if the logical display is presented on 166 * more than one physical display. 167 * </p> 168 */ 169 public float physicalXDpi; 170 171 /** 172 * The exact physical pixels per inch of the screen in the Y dimension. 173 * <p> 174 * The value of this field is indeterminate if the logical display is presented on 175 * more than one physical display. 176 * </p> 177 */ 178 public float physicalYDpi; 179 180 public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() { 181 @Override 182 public DisplayInfo createFromParcel(Parcel source) { 183 return new DisplayInfo(source); 184 } 185 186 @Override 187 public DisplayInfo[] newArray(int size) { 188 return new DisplayInfo[size]; 189 } 190 }; 191 DisplayInfo()192 public DisplayInfo() { 193 } 194 DisplayInfo(DisplayInfo other)195 public DisplayInfo(DisplayInfo other) { 196 copyFrom(other); 197 } 198 DisplayInfo(Parcel source)199 private DisplayInfo(Parcel source) { 200 readFromParcel(source); 201 } 202 203 @Override equals(Object o)204 public boolean equals(Object o) { 205 return o instanceof DisplayInfo && equals((DisplayInfo)o); 206 } 207 equals(DisplayInfo other)208 public boolean equals(DisplayInfo other) { 209 return other != null 210 && layerStack == other.layerStack 211 && flags == other.flags 212 && type == other.type 213 && Objects.equal(address, other.address) 214 && Objects.equal(name, other.name) 215 && appWidth == other.appWidth 216 && appHeight == other.appHeight 217 && smallestNominalAppWidth == other.smallestNominalAppWidth 218 && smallestNominalAppHeight == other.smallestNominalAppHeight 219 && largestNominalAppWidth == other.largestNominalAppWidth 220 && largestNominalAppHeight == other.largestNominalAppHeight 221 && logicalWidth == other.logicalWidth 222 && logicalHeight == other.logicalHeight 223 && overscanLeft == other.overscanLeft 224 && overscanTop == other.overscanTop 225 && overscanRight == other.overscanRight 226 && overscanBottom == other.overscanBottom 227 && rotation == other.rotation 228 && refreshRate == other.refreshRate 229 && logicalDensityDpi == other.logicalDensityDpi 230 && physicalXDpi == other.physicalXDpi 231 && physicalYDpi == other.physicalYDpi; 232 } 233 234 @Override hashCode()235 public int hashCode() { 236 return 0; // don't care 237 } 238 copyFrom(DisplayInfo other)239 public void copyFrom(DisplayInfo other) { 240 layerStack = other.layerStack; 241 flags = other.flags; 242 type = other.type; 243 address = other.address; 244 name = other.name; 245 appWidth = other.appWidth; 246 appHeight = other.appHeight; 247 smallestNominalAppWidth = other.smallestNominalAppWidth; 248 smallestNominalAppHeight = other.smallestNominalAppHeight; 249 largestNominalAppWidth = other.largestNominalAppWidth; 250 largestNominalAppHeight = other.largestNominalAppHeight; 251 logicalWidth = other.logicalWidth; 252 logicalHeight = other.logicalHeight; 253 overscanLeft = other.overscanLeft; 254 overscanTop = other.overscanTop; 255 overscanRight = other.overscanRight; 256 overscanBottom = other.overscanBottom; 257 rotation = other.rotation; 258 refreshRate = other.refreshRate; 259 logicalDensityDpi = other.logicalDensityDpi; 260 physicalXDpi = other.physicalXDpi; 261 physicalYDpi = other.physicalYDpi; 262 } 263 readFromParcel(Parcel source)264 public void readFromParcel(Parcel source) { 265 layerStack = source.readInt(); 266 flags = source.readInt(); 267 type = source.readInt(); 268 address = source.readString(); 269 name = source.readString(); 270 appWidth = source.readInt(); 271 appHeight = source.readInt(); 272 smallestNominalAppWidth = source.readInt(); 273 smallestNominalAppHeight = source.readInt(); 274 largestNominalAppWidth = source.readInt(); 275 largestNominalAppHeight = source.readInt(); 276 logicalWidth = source.readInt(); 277 logicalHeight = source.readInt(); 278 overscanLeft = source.readInt(); 279 overscanTop = source.readInt(); 280 overscanRight = source.readInt(); 281 overscanBottom = source.readInt(); 282 rotation = source.readInt(); 283 refreshRate = source.readFloat(); 284 logicalDensityDpi = source.readInt(); 285 physicalXDpi = source.readFloat(); 286 physicalYDpi = source.readFloat(); 287 } 288 289 @Override writeToParcel(Parcel dest, int flags)290 public void writeToParcel(Parcel dest, int flags) { 291 dest.writeInt(layerStack); 292 dest.writeInt(this.flags); 293 dest.writeInt(type); 294 dest.writeString(address); 295 dest.writeString(name); 296 dest.writeInt(appWidth); 297 dest.writeInt(appHeight); 298 dest.writeInt(smallestNominalAppWidth); 299 dest.writeInt(smallestNominalAppHeight); 300 dest.writeInt(largestNominalAppWidth); 301 dest.writeInt(largestNominalAppHeight); 302 dest.writeInt(logicalWidth); 303 dest.writeInt(logicalHeight); 304 dest.writeInt(overscanLeft); 305 dest.writeInt(overscanTop); 306 dest.writeInt(overscanRight); 307 dest.writeInt(overscanBottom); 308 dest.writeInt(rotation); 309 dest.writeFloat(refreshRate); 310 dest.writeInt(logicalDensityDpi); 311 dest.writeFloat(physicalXDpi); 312 dest.writeFloat(physicalYDpi); 313 } 314 315 @Override describeContents()316 public int describeContents() { 317 return 0; 318 } 319 getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih)320 public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) { 321 getMetricsWithSize(outMetrics, cih, appWidth, appHeight); 322 } 323 getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih)324 public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfoHolder cih) { 325 getMetricsWithSize(outMetrics, cih, logicalWidth, logicalHeight); 326 } 327 getNaturalWidth()328 public int getNaturalWidth() { 329 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 330 logicalWidth : logicalHeight; 331 } 332 getNaturalHeight()333 public int getNaturalHeight() { 334 return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ? 335 logicalHeight : logicalWidth; 336 } 337 getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih, int width, int height)338 private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfoHolder cih, 339 int width, int height) { 340 outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi; 341 outMetrics.noncompatWidthPixels = outMetrics.widthPixels = width; 342 outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height; 343 344 outMetrics.density = outMetrics.noncompatDensity = 345 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE; 346 outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density; 347 outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi; 348 outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi; 349 350 if (cih != null) { 351 CompatibilityInfo ci = cih.getIfNeeded(); 352 if (ci != null) { 353 ci.applyToDisplayMetrics(outMetrics); 354 } 355 } 356 } 357 358 // For debugging purposes 359 @Override toString()360 public String toString() { 361 StringBuilder sb = new StringBuilder(); 362 sb.append("DisplayInfo{\""); 363 sb.append(name); 364 sb.append("\", app "); 365 sb.append(appWidth); 366 sb.append(" x "); 367 sb.append(appHeight); 368 sb.append(", real "); 369 sb.append(logicalWidth); 370 sb.append(" x "); 371 sb.append(logicalHeight); 372 if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) { 373 sb.append(", overscan ("); 374 sb.append(overscanLeft); 375 sb.append(","); 376 sb.append(overscanTop); 377 sb.append(","); 378 sb.append(overscanRight); 379 sb.append(","); 380 sb.append(overscanBottom); 381 sb.append(")"); 382 } 383 sb.append(", largest app "); 384 sb.append(largestNominalAppWidth); 385 sb.append(" x "); 386 sb.append(largestNominalAppHeight); 387 sb.append(", smallest app "); 388 sb.append(smallestNominalAppWidth); 389 sb.append(" x "); 390 sb.append(smallestNominalAppHeight); 391 sb.append(", "); 392 sb.append(refreshRate); 393 sb.append(" fps, rotation"); 394 sb.append(rotation); 395 sb.append(", density "); 396 sb.append(logicalDensityDpi); 397 sb.append(" ("); 398 sb.append(physicalXDpi); 399 sb.append(" x "); 400 sb.append(physicalYDpi); 401 sb.append(") dpi, layerStack "); 402 sb.append(layerStack); 403 sb.append(", type "); 404 sb.append(Display.typeToString(type)); 405 sb.append(", address "); 406 sb.append(address); 407 sb.append(flagsToString(flags)); 408 sb.append("}"); 409 return sb.toString(); 410 } 411 flagsToString(int flags)412 private static String flagsToString(int flags) { 413 StringBuilder result = new StringBuilder(); 414 if ((flags & Display.FLAG_SECURE) != 0) { 415 result.append(", FLAG_SECURE"); 416 } 417 if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 418 result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 419 } 420 return result.toString(); 421 } 422 } 423