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 com.android.server.display; 18 19 import android.hardware.display.DeviceProductInfo; 20 import android.hardware.display.DisplayViewport; 21 import android.util.DisplayMetrics; 22 import android.view.Display; 23 import android.view.DisplayAddress; 24 import android.view.DisplayCutout; 25 import android.view.DisplayEventReceiver; 26 import android.view.DisplayShape; 27 import android.view.RoundedCorners; 28 import android.view.Surface; 29 30 import com.android.internal.display.BrightnessSynchronizer; 31 32 import java.util.Arrays; 33 import java.util.Objects; 34 35 /** 36 * Describes the characteristics of a physical display device. 37 */ 38 final class DisplayDeviceInfo { 39 /** 40 * Flag: Indicates that this display device should be considered the default display 41 * device of the system. 42 */ 43 public static final int FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY = 1 << 0; 44 45 /** 46 * Flag: Indicates that the orientation of this display device is coupled to the 47 * rotation of its associated logical display. 48 * <p> 49 * This flag should be applied to the default display to indicate that the user 50 * physically rotates the display when content is presented in a different orientation. 51 * The display manager will apply a coordinate transformation assuming that the 52 * physical orientation of the display matches the logical orientation of its content. 53 * </p><p> 54 * The flag should not be set when the display device is mounted in a fixed orientation 55 * such as on a desk. The display manager will apply a coordinate transformation 56 * such as a scale and translation to letterbox or pillarbox format under the 57 * assumption that the physical orientation of the display is invariant. 58 * </p> 59 */ 60 public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1; 61 62 /** 63 * Flag: Indicates that this display device has secure video output, such as HDCP. 64 */ 65 public static final int FLAG_SECURE = 1 << 2; 66 67 /** 68 * Flag: Indicates that this display device supports compositing 69 * from gralloc protected buffers. 70 */ 71 public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3; 72 73 /** 74 * Flag: Indicates that the display device is owned by a particular application 75 * and that no other application should be able to interact with it. 76 * Should typically be used together with {@link #FLAG_OWN_CONTENT_ONLY}. 77 */ 78 public static final int FLAG_PRIVATE = 1 << 4; 79 80 /** 81 * Flag: Indicates that the display device is not blanked automatically by 82 * the power manager. 83 */ 84 public static final int FLAG_NEVER_BLANK = 1 << 5; 85 86 /** 87 * Flag: Indicates that the display is suitable for presentations. 88 */ 89 public static final int FLAG_PRESENTATION = 1 << 6; 90 91 /** 92 * Flag: Only show this display's own content; do not mirror 93 * the content of another display. 94 */ 95 public static final int FLAG_OWN_CONTENT_ONLY = 1 << 7; 96 97 /** 98 * Flag: This display device has a round shape. 99 */ 100 public static final int FLAG_ROUND = 1 << 8; 101 102 /** 103 * Flag: This display can show its content when non-secure keyguard is shown. 104 */ 105 // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard 106 public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 9; 107 108 /** 109 * Flag: This display will destroy its content on removal. 110 * @hide 111 */ 112 // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY 113 public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10; 114 115 /** 116 * Flag: The display cutout of this display is masked. 117 * @hide 118 */ 119 public static final int FLAG_MASK_DISPLAY_CUTOUT = 1 << 11; 120 121 /** 122 * Flag: This flag identifies secondary displays that should show system decorations, such as 123 * status bar, navigation bar, home activity or IME. 124 * <p>Note that this flag doesn't work without {@link #FLAG_TRUSTED}</p> 125 * @hide 126 */ 127 // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors 128 public static final int FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 12; 129 130 /** 131 * Flag: The display is trusted to show system decorations and receive inputs without users' 132 * touch. 133 * @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS 134 */ 135 public static final int FLAG_TRUSTED = 1 << 13; 136 137 /** 138 * Flag: Indicates that the display should not be a part of the default {@link DisplayGroup} and 139 * instead be part of a new {@link DisplayGroup}. 140 * 141 * @hide 142 */ 143 public static final int FLAG_OWN_DISPLAY_GROUP = 1 << 14; 144 145 /** 146 * Flag: Indicates that the display should always be unlocked. Only valid on virtual displays 147 * that aren't in the default display group. 148 * @see #FLAG_OWN_DISPLAY_GROUP and #FLAG_DEVICE_DISPLAY_GROUP 149 * @hide 150 */ 151 public static final int FLAG_ALWAYS_UNLOCKED = 1 << 15; 152 153 /** 154 * Flag: Indicates that the display should not play sound effects or perform haptic feedback 155 * when the user touches the screen. 156 * 157 * @hide 158 */ 159 public static final int FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 16; 160 161 /** 162 * Flag: Indicates that the display maintains its own focus and touch mode. 163 * 164 * This flag is similar to {@link com.android.internal.R.bool.config_perDisplayFocusEnabled} in 165 * behavior, but only applies to the specific display instead of system-wide to all displays. 166 * 167 * Note: The display must be trusted in order to have its own focus. 168 * 169 * @see #FLAG_TRUSTED 170 * @hide 171 */ 172 public static final int FLAG_OWN_FOCUS = 1 << 17; 173 174 /** 175 * Flag: indicates that the display should not be a part of the default {@link DisplayGroup} and 176 * instead be part of a {@link DisplayGroup} associated with the Virtual Device. 177 * 178 * @hide 179 */ 180 public static final int FLAG_DEVICE_DISPLAY_GROUP = 1 << 18; 181 182 /** 183 * Flag: Indicates that the display should not become the top focused display by stealing the 184 * top focus from another display. 185 * 186 * @see Display#FLAG_STEAL_TOP_FOCUS_DISABLED 187 * @hide 188 */ 189 public static final int FLAG_STEAL_TOP_FOCUS_DISABLED = 1 << 19; 190 191 /** 192 * Touch attachment: Display does not receive touch. 193 */ 194 public static final int TOUCH_NONE = 0; 195 196 /** 197 * Touch attachment: Touch input is via the internal interface. 198 */ 199 public static final int TOUCH_INTERNAL = 1; 200 201 /** 202 * Touch attachment: Touch input is via an external interface, such as USB. 203 */ 204 public static final int TOUCH_EXTERNAL = 2; 205 206 /** 207 * Touch attachment: Touch input is via an input device matching {@link VirtualDisplay}'s 208 * uniqueId. 209 * @hide 210 */ 211 public static final int TOUCH_VIRTUAL = 3; 212 213 /** 214 * Diff result: The {@link #state} or {@link #committedState} fields differ. 215 */ 216 public static final int DIFF_STATE = 1 << 0; 217 218 /** 219 * Diff result: Other fields differ. 220 */ 221 public static final int DIFF_OTHER = 1 << 1; 222 223 /** 224 * Diff result: The color mode fields differ. 225 */ 226 public static final int DIFF_COLOR_MODE = 1 << 2; 227 228 /** 229 * Diff result: The hdr/sdr ratio differs 230 */ 231 public static final int DIFF_HDR_SDR_RATIO = 1 << 3; 232 233 /** 234 * Diff result: Catch-all for "everything changed" 235 */ 236 public static final int DIFF_EVERYTHING = 0XFFFFFFFF; 237 238 /** 239 * Gets the name of the display device, which may be derived from EDID or 240 * other sources. The name may be localized and displayed to the user. 241 */ 242 public String name; 243 244 /** 245 * Unique Id of display device. 246 */ 247 public String uniqueId; 248 249 /** 250 * The width of the display in its natural orientation, in pixels. 251 * This value is not affected by display rotation. 252 */ 253 public int width; 254 255 /** 256 * The height of the display in its natural orientation, in pixels. 257 * This value is not affected by display rotation. 258 */ 259 public int height; 260 261 /** 262 * The active mode of the display. 263 */ 264 public int modeId; 265 266 /** 267 * The render frame rate this display is scheduled at. 268 * @see android.view.DisplayInfo#renderFrameRate for more details. 269 */ 270 public float renderFrameRate; 271 272 /** 273 * The default mode of the display. 274 */ 275 public int defaultModeId; 276 277 /** 278 * The supported modes of the display. 279 */ 280 public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY; 281 282 /** The active color mode of the display */ 283 public int colorMode; 284 285 /** The supported color modes of the display */ 286 public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT }; 287 288 /** 289 * The HDR capabilities this display claims to support. 290 */ 291 public Display.HdrCapabilities hdrCapabilities; 292 293 /** 294 * Indicates whether this display supports Auto Low Latency Mode. 295 */ 296 public boolean allmSupported; 297 298 /** 299 * Indicates whether this display suppors Game content type. 300 */ 301 public boolean gameContentTypeSupported; 302 303 /** 304 * The nominal apparent density of the display in DPI used for layout calculations. 305 * This density is sensitive to the viewing distance. A big TV and a tablet may have 306 * the same apparent density even though the pixels on the TV are much bigger than 307 * those on the tablet. 308 */ 309 public int densityDpi; 310 311 /** 312 * The physical density of the display in DPI in the X direction. 313 * This density should specify the physical size of each pixel. 314 */ 315 public float xDpi; 316 317 /** 318 * The physical density of the display in DPI in the X direction. 319 * This density should specify the physical size of each pixel. 320 */ 321 public float yDpi; 322 323 /** 324 * This is a positive value indicating the phase offset of the VSYNC events provided by 325 * Choreographer relative to the display refresh. For example, if Choreographer reports 326 * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos). 327 */ 328 public long appVsyncOffsetNanos; 329 330 /** 331 * This is how far in advance a buffer must be queued for presentation at 332 * a given time. If you want a buffer to appear on the screen at 333 * time N, you must submit the buffer before (N - bufferDeadlineNanos). 334 */ 335 public long presentationDeadlineNanos; 336 337 /** 338 * Display flags. 339 */ 340 public int flags; 341 342 /** 343 * The {@link DisplayCutout} if present or {@code null} otherwise. 344 */ 345 public DisplayCutout displayCutout; 346 347 /** 348 * The {@link RoundedCorners} if present or {@code null} otherwise. 349 */ 350 public RoundedCorners roundedCorners; 351 352 /** 353 * The {@link RoundedCorners} if present or {@code null} otherwise. 354 */ 355 public DisplayShape displayShape; 356 357 /** 358 * The touch attachment, per {@link DisplayViewport#touch}. 359 */ 360 public int touch; 361 362 /** 363 * The additional rotation to apply to all content presented on the display device 364 * relative to its physical coordinate system. Default is {@link Surface#ROTATION_0}. 365 * <p> 366 * This field can be used to compensate for the fact that the display has been 367 * physically rotated relative to its natural orientation such as an HDMI monitor 368 * that has been mounted sideways to appear to be portrait rather than landscape. 369 * </p> 370 */ 371 public int rotation = Surface.ROTATION_0; 372 373 /** 374 * Display type. 375 */ 376 public int type; 377 378 /** 379 * Display address, or null if none. 380 * Interpretation varies by display type. 381 */ 382 public DisplayAddress address; 383 384 /** 385 * Product-specific information about the display or the directly connected device on the 386 * display chain. For example, if the display is transitively connected, this field may contain 387 * product information about the intermediate device. 388 */ 389 public DeviceProductInfo deviceProductInfo; 390 391 /** 392 * Display state. 393 */ 394 public int state = Display.STATE_ON; 395 396 /** 397 * Display committed state. 398 * 399 * This matches {@link DisplayDeviceInfo#state} only after the power state change finishes. 400 */ 401 public int committedState = Display.STATE_UNKNOWN; 402 403 /** 404 * The UID of the application that owns this display, or zero if it is owned by the system. 405 * <p> 406 * If the display is private, then only the owner can use it. 407 * </p> 408 */ 409 public int ownerUid; 410 411 /** 412 * The package name of the application that owns this display, or null if it is 413 * owned by the system. 414 * <p> 415 * If the display is private, then only the owner can use it. 416 * </p> 417 */ 418 public String ownerPackageName; 419 420 public DisplayEventReceiver.FrameRateOverride[] frameRateOverrides = 421 new DisplayEventReceiver.FrameRateOverride[0]; 422 423 public float brightnessMinimum; 424 public float brightnessMaximum; 425 public float brightnessDefault; 426 427 // NaN means unsupported 428 public float hdrSdrRatio = Float.NaN; 429 430 /** 431 * Install orientation of display panel relative to its natural orientation. 432 */ 433 @Surface.Rotation 434 public int installOrientation = Surface.ROTATION_0; 435 setAssumedDensityForExternalDisplay(int width, int height)436 public void setAssumedDensityForExternalDisplay(int width, int height) { 437 densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080; 438 // Technically, these values should be smaller than the apparent density 439 // but we don't know the physical size of the display. 440 xDpi = densityDpi; 441 yDpi = densityDpi; 442 } 443 444 @Override equals(Object o)445 public boolean equals(Object o) { 446 return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o); 447 } 448 equals(DisplayDeviceInfo other)449 public boolean equals(DisplayDeviceInfo other) { 450 return other != null && diff(other) == 0; 451 } 452 453 /** 454 * Computes the difference between display device infos. 455 * Assumes other is not null. 456 */ diff(DisplayDeviceInfo other)457 public int diff(DisplayDeviceInfo other) { 458 int diff = 0; 459 if (state != other.state || committedState != other.committedState) { 460 diff |= DIFF_STATE; 461 } 462 if (colorMode != other.colorMode) { 463 diff |= DIFF_COLOR_MODE; 464 } 465 if (!BrightnessSynchronizer.floatEquals(hdrSdrRatio, other.hdrSdrRatio)) { 466 diff |= DIFF_HDR_SDR_RATIO; 467 } 468 if (!Objects.equals(name, other.name) 469 || !Objects.equals(uniqueId, other.uniqueId) 470 || width != other.width 471 || height != other.height 472 || modeId != other.modeId 473 || renderFrameRate != other.renderFrameRate 474 || defaultModeId != other.defaultModeId 475 || !Arrays.equals(supportedModes, other.supportedModes) 476 || !Arrays.equals(supportedColorModes, other.supportedColorModes) 477 || !Objects.equals(hdrCapabilities, other.hdrCapabilities) 478 || allmSupported != other.allmSupported 479 || gameContentTypeSupported != other.gameContentTypeSupported 480 || densityDpi != other.densityDpi 481 || xDpi != other.xDpi 482 || yDpi != other.yDpi 483 || appVsyncOffsetNanos != other.appVsyncOffsetNanos 484 || presentationDeadlineNanos != other.presentationDeadlineNanos 485 || flags != other.flags 486 || !Objects.equals(displayCutout, other.displayCutout) 487 || touch != other.touch 488 || rotation != other.rotation 489 || type != other.type 490 || !Objects.equals(address, other.address) 491 || !Objects.equals(deviceProductInfo, other.deviceProductInfo) 492 || ownerUid != other.ownerUid 493 || !Objects.equals(ownerPackageName, other.ownerPackageName) 494 || !Arrays.equals(frameRateOverrides, other.frameRateOverrides) 495 || !BrightnessSynchronizer.floatEquals(brightnessMinimum, other.brightnessMinimum) 496 || !BrightnessSynchronizer.floatEquals(brightnessMaximum, other.brightnessMaximum) 497 || !BrightnessSynchronizer.floatEquals(brightnessDefault, 498 other.brightnessDefault) 499 || !Objects.equals(roundedCorners, other.roundedCorners) 500 || installOrientation != other.installOrientation 501 || !Objects.equals(displayShape, other.displayShape)) { 502 diff |= DIFF_OTHER; 503 } 504 return diff; 505 } 506 507 @Override hashCode()508 public int hashCode() { 509 return 0; // don't care 510 } 511 copyFrom(DisplayDeviceInfo other)512 public void copyFrom(DisplayDeviceInfo other) { 513 name = other.name; 514 uniqueId = other.uniqueId; 515 width = other.width; 516 height = other.height; 517 modeId = other.modeId; 518 renderFrameRate = other.renderFrameRate; 519 defaultModeId = other.defaultModeId; 520 supportedModes = other.supportedModes; 521 colorMode = other.colorMode; 522 supportedColorModes = other.supportedColorModes; 523 hdrCapabilities = other.hdrCapabilities; 524 allmSupported = other.allmSupported; 525 gameContentTypeSupported = other.gameContentTypeSupported; 526 densityDpi = other.densityDpi; 527 xDpi = other.xDpi; 528 yDpi = other.yDpi; 529 appVsyncOffsetNanos = other.appVsyncOffsetNanos; 530 presentationDeadlineNanos = other.presentationDeadlineNanos; 531 flags = other.flags; 532 displayCutout = other.displayCutout; 533 touch = other.touch; 534 rotation = other.rotation; 535 type = other.type; 536 address = other.address; 537 deviceProductInfo = other.deviceProductInfo; 538 state = other.state; 539 committedState = other.committedState; 540 ownerUid = other.ownerUid; 541 ownerPackageName = other.ownerPackageName; 542 frameRateOverrides = other.frameRateOverrides; 543 brightnessMinimum = other.brightnessMinimum; 544 brightnessMaximum = other.brightnessMaximum; 545 brightnessDefault = other.brightnessDefault; 546 hdrSdrRatio = other.hdrSdrRatio; 547 roundedCorners = other.roundedCorners; 548 installOrientation = other.installOrientation; 549 displayShape = other.displayShape; 550 } 551 552 // For debugging purposes 553 @Override toString()554 public String toString() { 555 StringBuilder sb = new StringBuilder(); 556 sb.append("DisplayDeviceInfo{\""); 557 sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", "); 558 sb.append(width).append(" x ").append(height); 559 sb.append(", modeId ").append(modeId); 560 sb.append(", renderFrameRate ").append(renderFrameRate); 561 sb.append(", defaultModeId ").append(defaultModeId); 562 sb.append(", supportedModes ").append(Arrays.toString(supportedModes)); 563 sb.append(", colorMode ").append(colorMode); 564 sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes)); 565 sb.append(", hdrCapabilities ").append(hdrCapabilities); 566 sb.append(", allmSupported ").append(allmSupported); 567 sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported); 568 sb.append(", density ").append(densityDpi); 569 sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi"); 570 sb.append(", appVsyncOff ").append(appVsyncOffsetNanos); 571 sb.append(", presDeadline ").append(presentationDeadlineNanos); 572 if (displayCutout != null) { 573 sb.append(", cutout ").append(displayCutout); 574 } 575 sb.append(", touch ").append(touchToString(touch)); 576 sb.append(", rotation ").append(rotation); 577 sb.append(", type ").append(Display.typeToString(type)); 578 if (address != null) { 579 sb.append(", address ").append(address); 580 } 581 sb.append(", deviceProductInfo ").append(deviceProductInfo); 582 sb.append(", state ").append(Display.stateToString(state)); 583 sb.append(", committedState ").append(Display.stateToString(committedState)); 584 if (ownerUid != 0 || ownerPackageName != null) { 585 sb.append(", owner ").append(ownerPackageName); 586 sb.append(" (uid ").append(ownerUid).append(")"); 587 } 588 sb.append(", frameRateOverride "); 589 for (DisplayEventReceiver.FrameRateOverride frameRateOverride : frameRateOverrides) { 590 sb.append(frameRateOverride).append(" "); 591 } 592 sb.append(", brightnessMinimum ").append(brightnessMinimum); 593 sb.append(", brightnessMaximum ").append(brightnessMaximum); 594 sb.append(", brightnessDefault ").append(brightnessDefault); 595 sb.append(", hdrSdrRatio ").append(hdrSdrRatio); 596 if (roundedCorners != null) { 597 sb.append(", roundedCorners ").append(roundedCorners); 598 } 599 sb.append(flagsToString(flags)); 600 sb.append(", installOrientation ").append(installOrientation); 601 if (displayShape != null) { 602 sb.append(", displayShape ").append(displayShape); 603 } 604 sb.append("}"); 605 return sb.toString(); 606 } 607 touchToString(int touch)608 private static String touchToString(int touch) { 609 switch (touch) { 610 case TOUCH_NONE: 611 return "NONE"; 612 case TOUCH_INTERNAL: 613 return "INTERNAL"; 614 case TOUCH_EXTERNAL: 615 return "EXTERNAL"; 616 case TOUCH_VIRTUAL: 617 return "VIRTUAL"; 618 default: 619 return Integer.toString(touch); 620 } 621 } 622 flagsToString(int flags)623 private static String flagsToString(int flags) { 624 StringBuilder msg = new StringBuilder(); 625 if ((flags & FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY) != 0) { 626 msg.append(", FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY"); 627 } 628 if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) { 629 msg.append(", FLAG_ROTATES_WITH_CONTENT"); 630 } 631 if ((flags & FLAG_SECURE) != 0) { 632 msg.append(", FLAG_SECURE"); 633 } 634 if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) { 635 msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS"); 636 } 637 if ((flags & FLAG_PRIVATE) != 0) { 638 msg.append(", FLAG_PRIVATE"); 639 } 640 if ((flags & FLAG_NEVER_BLANK) != 0) { 641 msg.append(", FLAG_NEVER_BLANK"); 642 } 643 if ((flags & FLAG_PRESENTATION) != 0) { 644 msg.append(", FLAG_PRESENTATION"); 645 } 646 if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) { 647 msg.append(", FLAG_OWN_CONTENT_ONLY"); 648 } 649 if ((flags & FLAG_ROUND) != 0) { 650 msg.append(", FLAG_ROUND"); 651 } 652 if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) { 653 msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD"); 654 } 655 if ((flags & FLAG_DESTROY_CONTENT_ON_REMOVAL) != 0) { 656 msg.append(", FLAG_DESTROY_CONTENT_ON_REMOVAL"); 657 } 658 if ((flags & FLAG_MASK_DISPLAY_CUTOUT) != 0) { 659 msg.append(", FLAG_MASK_DISPLAY_CUTOUT"); 660 } 661 if ((flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) { 662 msg.append(", FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS"); 663 } 664 if ((flags & FLAG_TRUSTED) != 0) { 665 msg.append(", FLAG_TRUSTED"); 666 } 667 if ((flags & FLAG_OWN_DISPLAY_GROUP) != 0) { 668 msg.append(", FLAG_OWN_DISPLAY_GROUP"); 669 } 670 if ((flags & FLAG_ALWAYS_UNLOCKED) != 0) { 671 msg.append(", FLAG_ALWAYS_UNLOCKED"); 672 } 673 if ((flags & FLAG_TOUCH_FEEDBACK_DISABLED) != 0) { 674 msg.append(", FLAG_TOUCH_FEEDBACK_DISABLED"); 675 } 676 if ((flags & FLAG_OWN_FOCUS) != 0) { 677 msg.append(", FLAG_OWN_FOCUS"); 678 } 679 if ((flags & FLAG_STEAL_TOP_FOCUS_DISABLED) != 0) { 680 msg.append(", FLAG_STEAL_TOP_FOCUS_DISABLED"); 681 } 682 return msg.toString(); 683 } 684 } 685