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