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