DisplayDeviceInfo.java revision 7211d2eba8e02b5e7462313798fc25c0bd36ab2d
1fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown/*
2fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Copyright (C) 2012 The Android Open Source Project
3fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *
4fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * you may not use this file except in compliance with the License.
6fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * You may obtain a copy of the License at
7fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *
8fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown *
10fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Unless required by applicable law or agreed to in writing, software
11fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * See the License for the specific language governing permissions and
14fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * limitations under the License.
15fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown */
16fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
17fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brownpackage com.android.server.display;
18fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
194ccb823a9f62e57f9d221f83a97e82967e79a9e5Jeff Brownimport android.hardware.display.DisplayViewport;
20cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brownimport android.util.DisplayMetrics;
2192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brownimport android.view.Display;
2227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brownimport android.view.Surface;
23cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
243f145a2f958320766ae9240c7a57debc20d578aaMichael Wrightimport java.util.Arrays;
253f145a2f958320766ae9240c7a57debc20d578aaMichael Wright
264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownimport libcore.util.Objects;
274ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
28fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown/**
29fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown * Describes the characteristics of a physical display device.
30fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown */
314ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brownfinal class DisplayDeviceInfo {
324ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
334ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * Flag: Indicates that this display device should be considered the default display
344ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     * device of the system.
354ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
36bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
374ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
384ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
3927f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * Flag: Indicates that the orientation of this display device is coupled to the
4027f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * rotation of its associated logical display.
4127f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * <p>
4227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * This flag should be applied to the default display to indicate that the user
4327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * physically rotates the display when content is presented in a different orientation.
4427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * The display manager will apply a coordinate transformation assuming that the
4527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * physical orientation of the display matches the logical orientation of its content.
4627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * </p><p>
4727f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * The flag should not be set when the display device is mounted in a fixed orientation
4827f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * such as on a desk.  The display manager will apply a coordinate transformation
4927f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * such as a scale and translation to letterbox or pillarbox format under the
5027f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * assumption that the physical orientation of the display is invariant.
5127f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * </p>
524ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown     */
5327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1;
54c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown
55c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown    /**
5677aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown     * Flag: Indicates that this display device has secure video output, such as HDCP.
57c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown     */
5877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown    public static final int FLAG_SECURE = 1 << 2;
5977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown
6077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown    /**
6177aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown     * Flag: Indicates that this display device supports compositing
6277aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown     * from gralloc protected buffers.
6377aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown     */
6477aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown    public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3;
654ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
664ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    /**
67a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * Flag: Indicates that the display device is owned by a particular application
68a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * and that no other application should be able to interact with it.
69d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown     * Should typically be used together with {@link #FLAG_OWN_CONTENT_ONLY}.
70a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     */
71a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    public static final int FLAG_PRIVATE = 1 << 4;
72a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown
73a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    /**
74a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * Flag: Indicates that the display device is not blanked automatically by
75a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * the power manager.
76a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     */
77a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    public static final int FLAG_NEVER_BLANK = 1 << 5;
78a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown
79a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    /**
807d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown     * Flag: Indicates that the display is suitable for presentations.
817d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown     */
827d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown    public static final int FLAG_PRESENTATION = 1 << 6;
837d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown
847d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown    /**
85d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown     * Flag: Only show this display's own content; do not mirror
86d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown     * the content of another display.
87d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown     */
88d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown    public static final int FLAG_OWN_CONTENT_ONLY = 1 << 7;
89d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown
90d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown    /**
9149e7ff9647e6547c2b852944a5435a05794b9951Adam Powell     * Flag: This display device has a round shape.
9249e7ff9647e6547c2b852944a5435a05794b9951Adam Powell     */
9349e7ff9647e6547c2b852944a5435a05794b9951Adam Powell    public static final int FLAG_ROUND = 1 << 8;
9449e7ff9647e6547c2b852944a5435a05794b9951Adam Powell
9549e7ff9647e6547c2b852944a5435a05794b9951Adam Powell    /**
96fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3Andrii Kulian     * Flag: This display can show its content when non-secure keyguard is shown.
97fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3Andrii Kulian     */
987211d2eba8e02b5e7462313798fc25c0bd36ab2dAndrii Kulian    public static final int FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 9;
99fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3Andrii Kulian
100fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3Andrii Kulian    /**
101d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * Touch attachment: Display does not receive touch.
102d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     */
103d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    public static final int TOUCH_NONE = 0;
104d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
105d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    /**
106d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * Touch attachment: Touch input is via the internal interface.
107d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     */
108d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    public static final int TOUCH_INTERNAL = 1;
109d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
110d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    /**
111d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * Touch attachment: Touch input is via an external interface, such as USB.
112d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     */
113d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    public static final int TOUCH_EXTERNAL = 2;
114d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
115d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    /**
11610acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     * Diff result: The {@link #state} fields differ.
11710acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     */
11810acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    public static final int DIFF_STATE = 1 << 0;
11910acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown
12010acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    /**
12110acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     * Diff result: Other fields differ.
12210acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     */
12310acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    public static final int DIFF_OTHER = 1 << 1;
12410acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown
12510acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    /**
1261c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright     * Diff result: The color mode fields differ.
1271c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright     */
1281c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright    public static final int DIFF_COLOR_MODE = 1 << 2;
1291c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright
1301c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright    /**
131361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale     * Gets the name of the display device, which may be derived from EDID or
132361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale     * other sources. The name may be localized and displayed to the user.
133848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown     */
134848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown    public String name;
135848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown
136848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown    /**
137361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale     * Unique Id of display device.
138361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale     */
139361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale    public String uniqueId;
140361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale
141361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale    /**
142fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown     * The width of the display in its natural orientation, in pixels.
143fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown     * This value is not affected by display rotation.
144fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown     */
145fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public int width;
146fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
147fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    /**
148fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown     * The height of the display in its natural orientation, in pixels.
149fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown     * This value is not affected by display rotation.
150fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown     */
151fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public int height;
152fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
153cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    /**
154b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand     * The active mode of the display.
155cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     */
156b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand    public int modeId;
157cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
158cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    /**
159b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand     * The default mode of the display.
1603f145a2f958320766ae9240c7a57debc20d578aaMichael Wright     */
161b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand    public int defaultModeId;
162b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand
163b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand    /**
164b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand     * The supported modes of the display.
165b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand     */
166b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand    public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
1673f145a2f958320766ae9240c7a57debc20d578aaMichael Wright
1681c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright    /** The active color mode of the display */
1691c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright    public int colorMode;
17058e829f71d2c525309e5bb5a1c02dc64397df221Michael Wright
1711c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright    /** The supported color modes of the display */
1721c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright    public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
17358e829f71d2c525309e5bb5a1c02dc64397df221Michael Wright
1743f145a2f958320766ae9240c7a57debc20d578aaMichael Wright    /**
1759ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright     * The HDR capabilities this display claims to support.
1769ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright     */
1779ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright    public Display.HdrCapabilities hdrCapabilities;
1789ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright
1799ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright    /**
180cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * The nominal apparent density of the display in DPI used for layout calculations.
181cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * This density is sensitive to the viewing distance.  A big TV and a tablet may have
182cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * the same apparent density even though the pixels on the TV are much bigger than
183cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * those on the tablet.
184cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     */
185908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn    public int densityDpi;
186cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
187cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    /**
188cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * The physical density of the display in DPI in the X direction.
189cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * This density should specify the physical size of each pixel.
190cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     */
191fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public float xDpi;
192cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
193cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    /**
194cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * The physical density of the display in DPI in the X direction.
195cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * This density should specify the physical size of each pixel.
196cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     */
197fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public float yDpi;
198fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
199cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    /**
200e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     * This is a positive value indicating the phase offset of the VSYNC events provided by
201e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     * Choreographer relative to the display refresh.  For example, if Choreographer reports
202e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
203e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     */
204e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden    public long appVsyncOffsetNanos;
205e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden
206e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden    /**
207e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     * This is how far in advance a buffer must be queued for presentation at
208e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     * a given time.  If you want a buffer to appear on the screen at
209e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     * time N, you must submit the buffer before (N - bufferDeadlineNanos).
210e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden     */
211e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden    public long presentationDeadlineNanos;
212e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden
213e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden    /**
214cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     * Display flags.
215cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown     */
216bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    public int flags;
217bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
218d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    /**
219d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     * The touch attachment, per {@link DisplayViewport#touch}.
220d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown     */
221d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    public int touch;
222d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
22327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    /**
22427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * The additional rotation to apply to all content presented on the display device
22527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * relative to its physical coordinate system.  Default is {@link Surface#ROTATION_0}.
22627f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * <p>
22727f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * This field can be used to compensate for the fact that the display has been
22827f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * physically rotated relative to its natural orientation such as an HDMI monitor
22927f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * that has been mounted sideways to appear to be portrait rather than landscape.
23027f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     * </p>
23127f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown     */
23227f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown    public int rotation = Surface.ROTATION_0;
23327f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown
23492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown    /**
23592130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown     * Display type.
23692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown     */
23792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown    public int type;
23892130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown
23992130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown    /**
24092130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown     * Display address, or null if none.
24192130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown     * Interpretation varies by display type.
24292130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown     */
24392130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown    public String address;
24492130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown
245a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    /**
246037c33eae74bee2774897d969d48947f9abe254fJeff Brown     * Display state.
247037c33eae74bee2774897d969d48947f9abe254fJeff Brown     */
248037c33eae74bee2774897d969d48947f9abe254fJeff Brown    public int state = Display.STATE_ON;
249037c33eae74bee2774897d969d48947f9abe254fJeff Brown
250037c33eae74bee2774897d969d48947f9abe254fJeff Brown    /**
251a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * The UID of the application that owns this display, or zero if it is owned by the system.
252a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * <p>
253a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * If the display is private, then only the owner can use it.
254a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * </p>
255a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     */
256a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    public int ownerUid;
257a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown
258a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    /**
259a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * The package name of the application that owns this display, or null if it is
260a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * owned by the system.
261a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * <p>
262a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * If the display is private, then only the owner can use it.
263a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     * </p>
264a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown     */
265a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown    public String ownerPackageName;
266a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown
267cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    public void setAssumedDensityForExternalDisplay(int width, int height) {
268cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
269cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        // Technically, these values should be smaller than the apparent density
270cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        // but we don't know the physical size of the display.
271cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        xDpi = densityDpi;
272cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown        yDpi = densityDpi;
273cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown    }
274cbad976b2a36a0895ca94510d5208a86f66cf596Jeff Brown
2754ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    @Override
2764ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public boolean equals(Object o) {
2774ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o);
2784ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
2794ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
2804ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public boolean equals(DisplayDeviceInfo other) {
28110acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        return other != null && diff(other) == 0;
28210acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    }
28310acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown
28410acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    /**
28510acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     * Computes the difference between display device infos.
28610acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     * Assumes other is not null.
28710acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown     */
28810acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown    public int diff(DisplayDeviceInfo other) {
28910acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        int diff = 0;
29010acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        if (state != other.state) {
29110acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown            diff |= DIFF_STATE;
29210acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        }
2931c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright        if (colorMode != other.colorMode) {
2941c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright            diff |= DIFF_COLOR_MODE;
2951c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright        }
29610acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        if (!Objects.equal(name, other.name)
29710acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || !Objects.equal(uniqueId, other.uniqueId)
29810acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || width != other.width
29910acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || height != other.height
300b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand                || modeId != other.modeId
301b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand                || defaultModeId != other.defaultModeId
302b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand                || !Arrays.equals(supportedModes, other.supportedModes)
3031c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright                || !Arrays.equals(supportedColorModes, other.supportedColorModes)
3049ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright                || !Objects.equal(hdrCapabilities, other.hdrCapabilities)
30510acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || densityDpi != other.densityDpi
30610acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || xDpi != other.xDpi
30710acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || yDpi != other.yDpi
30810acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || appVsyncOffsetNanos != other.appVsyncOffsetNanos
30910acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || presentationDeadlineNanos != other.presentationDeadlineNanos
31010acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || flags != other.flags
31110acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || touch != other.touch
31210acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || rotation != other.rotation
31310acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || type != other.type
31410acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || !Objects.equal(address, other.address)
31510acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || ownerUid != other.ownerUid
31610acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown                || !Objects.equal(ownerPackageName, other.ownerPackageName)) {
31710acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown            diff |= DIFF_OTHER;
31810acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        }
31910acf6d3efde60977d2d2e82b90c53d722d9d357Jeff Brown        return diff;
3204ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
3214ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
3224ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    @Override
3234ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    public int hashCode() {
3244ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown        return 0; // don't care
3254ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown    }
3264ed8fe75e1dde1a2b9576f3862aecc5a572c56b5Jeff Brown
327fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public void copyFrom(DisplayDeviceInfo other) {
328848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown        name = other.name;
329361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale        uniqueId = other.uniqueId;
330fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        width = other.width;
331fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        height = other.height;
332b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand        modeId = other.modeId;
333b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand        defaultModeId = other.defaultModeId;
334b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand        supportedModes = other.supportedModes;
3351c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright        colorMode = other.colorMode;
3361c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright        supportedColorModes = other.supportedColorModes;
3379ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright        hdrCapabilities = other.hdrCapabilities;
338908aecc3a63c5520d5b11da14a9383f885b7d126Dianne Hackborn        densityDpi = other.densityDpi;
339fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        xDpi = other.xDpi;
340fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown        yDpi = other.yDpi;
341e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden        appVsyncOffsetNanos = other.appVsyncOffsetNanos;
342e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden        presentationDeadlineNanos = other.presentationDeadlineNanos;
343bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        flags = other.flags;
344d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        touch = other.touch;
34527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown        rotation = other.rotation;
34692130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown        type = other.type;
34792130f6407dc51c58b3b941d28a6daf4e04b8d62Jeff Brown        address = other.address;
348037c33eae74bee2774897d969d48947f9abe254fJeff Brown        state = other.state;
349a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        ownerUid = other.ownerUid;
350a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        ownerPackageName = other.ownerPackageName;
351fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    }
352fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown
353848c2dc93b6795e171f3dd6f64ea0be65e2762caJeff Brown    // For debugging purposes
354fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    @Override
355fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    public String toString() {
356a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        StringBuilder sb = new StringBuilder();
357a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append("DisplayDeviceInfo{\"");
358361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale        sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", ");
359361ca21acc0831a9f8bbb259bb30218c252a2aa0Wale Ogunwale        sb.append(width).append(" x ").append(height);
360b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand        sb.append(", modeId ").append(modeId);
361b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand        sb.append(", defaultModeId ").append(defaultModeId);
362b3b9eb3cfc5b3b3609a5d01258315798b38a5cf9P.Y. Laligand        sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
3631c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright        sb.append(", colorMode ").append(colorMode);
3641c9977b762b4bac46b4470f04c898bfd17da5d90Michael Wright        sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes));
3659ff94c0251722c44eece7c3561b4ed36b286d4a8Michael Wright        sb.append(", HdrCapabilities ").append(hdrCapabilities);
3663f145a2f958320766ae9240c7a57debc20d578aaMichael Wright        sb.append(", density ").append(densityDpi);
367a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
368e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden        sb.append(", appVsyncOff ").append(appVsyncOffsetNanos);
369e8b1aeb51e1e5da64f1d4fd40f2ee1e815886fe5Andy McFadden        sb.append(", presDeadline ").append(presentationDeadlineNanos);
370a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append(", touch ").append(touchToString(touch));
371a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append(", rotation ").append(rotation);
372a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append(", type ").append(Display.typeToString(type));
373a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        if (address != null) {
374a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown            sb.append(", address ").append(address);
375a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        }
376037c33eae74bee2774897d969d48947f9abe254fJeff Brown        sb.append(", state ").append(Display.stateToString(state));
377a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        if (ownerUid != 0 || ownerPackageName != null) {
378a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown            sb.append(", owner ").append(ownerPackageName);
379a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown            sb.append(" (uid ").append(ownerUid).append(")");
380a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        }
381a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append(flagsToString(flags));
382a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        sb.append("}");
383a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        return sb.toString();
384d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    }
385d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown
386d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown    private static String touchToString(int touch) {
387d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        switch (touch) {
388d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            case TOUCH_NONE:
389d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                return "NONE";
390d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            case TOUCH_INTERNAL:
391d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                return "INTERNAL";
392d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            case TOUCH_EXTERNAL:
393d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                return "EXTERNAL";
394d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown            default:
395d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown                return Integer.toString(touch);
396d728bf514f257670fcb9aa22c6eaf97626072c93Jeff Brown        }
397bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    }
398bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown
399bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown    private static String flagsToString(int flags) {
400bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        StringBuilder msg = new StringBuilder();
401bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
402bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown            msg.append(", FLAG_DEFAULT_DISPLAY");
403bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
40427f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown        if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
40527f1d674bf9fb53af7facdcb746912e036d5bf75Jeff Brown            msg.append(", FLAG_ROTATES_WITH_CONTENT");
406c5df37c285221d0fb113f55b9e78b35632241d3fJeff Brown        }
40777aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        if ((flags & FLAG_SECURE) != 0) {
40877aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown            msg.append(", FLAG_SECURE");
40977aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        }
41077aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown        if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
41177aebfdbae489c3712ae3f9bca29d01fb1f09dc2Jeff Brown            msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
412bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        }
413a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        if ((flags & FLAG_PRIVATE) != 0) {
414a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown            msg.append(", FLAG_PRIVATE");
415a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        }
416a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        if ((flags & FLAG_NEVER_BLANK) != 0) {
417a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown            msg.append(", FLAG_NEVER_BLANK");
418a506a6ec94863a35acca9feb165db76ddac3892cJeff Brown        }
4197d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown        if ((flags & FLAG_PRESENTATION) != 0) {
4207d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown            msg.append(", FLAG_PRESENTATION");
4217d00affce6e25b22fd8fc135933b3bf6b547a0dcJeff Brown        }
422d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown        if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) {
423d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown            msg.append(", FLAG_OWN_CONTENT_ONLY");
424d14c8c9039c0056e1f30ad5d410c8fde20d63df5Jeff Brown        }
42549e7ff9647e6547c2b852944a5435a05794b9951Adam Powell        if ((flags & FLAG_ROUND) != 0) {
42649e7ff9647e6547c2b852944a5435a05794b9951Adam Powell            msg.append(", FLAG_ROUND");
42749e7ff9647e6547c2b852944a5435a05794b9951Adam Powell        }
4287211d2eba8e02b5e7462313798fc25c0bd36ab2dAndrii Kulian        if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
4297211d2eba8e02b5e7462313798fc25c0bd36ab2dAndrii Kulian            msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD");
430fc8f82bc6b587bddd2aeaddc54c1ea3f598bb9c3Andrii Kulian        }
431bd6e1500aedc5461e832f69e76341bff0e55fa2bJeff Brown        return msg.toString();
432fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown    }
433fa25bf5382467b1018bd9af7f1cb30a23d7d59f7Jeff Brown}
434