blob: 015571255f0d5ca161b2ebf9996617c780b0089a [file] [log] [blame]
Wale Ogunwale828ff7e2017-11-14 01:01:29 +00001/*
2 * Copyright (C) 2017 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
Adrian Roose99bc052017-11-20 17:55:31 +010014 * limitations under the License.
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000015 */
16
Adrian Roose99bc052017-11-20 17:55:31 +010017package com.android.server.wm;
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000018
19import static android.view.Surface.ROTATION_180;
20import static android.view.Surface.ROTATION_270;
21import static android.view.Surface.ROTATION_90;
22import static com.android.server.wm.proto.DisplayFramesProto.STABLE_BOUNDS;
23
Adrian Roos5c6b6222017-11-07 17:36:10 +010024import android.annotation.NonNull;
Adrian Roos000cf5e2017-11-10 15:55:18 +010025import android.graphics.Point;
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000026import android.graphics.Rect;
27import android.util.proto.ProtoOutputStream;
Adrian Roos5c6b6222017-11-07 17:36:10 +010028import android.view.DisplayCutout;
Adrian Roose99bc052017-11-20 17:55:31 +010029import android.view.DisplayInfo;
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000030
Adrian Roos000cf5e2017-11-10 15:55:18 +010031import com.android.internal.annotations.VisibleForTesting;
32
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000033import java.io.PrintWriter;
Adrian Roos000cf5e2017-11-10 15:55:18 +010034import java.util.Arrays;
Wale Ogunwale828ff7e2017-11-14 01:01:29 +000035
36/**
37 * Container class for all the display frames that affect how we do window layout on a display.
38 * @hide
39 */
40public class DisplayFrames {
41 public final int mDisplayId;
42
43 /**
44 * The current size of the screen; really; extends into the overscan area of the screen and
45 * doesn't account for any system elements like the status bar.
46 */
47 public final Rect mOverscan = new Rect();
48
49 /**
50 * The current visible size of the screen; really; (ir)regardless of whether the status bar can
51 * be hidden but not extending into the overscan area.
52 */
53 public final Rect mUnrestricted = new Rect();
54
55 /** Like mOverscan*, but allowed to move into the overscan region where appropriate. */
56 public final Rect mRestrictedOverscan = new Rect();
57
58 /**
59 * The current size of the screen; these may be different than (0,0)-(dw,dh) if the status bar
60 * can't be hidden; in that case it effectively carves out that area of the display from all
61 * other windows.
62 */
63 public final Rect mRestricted = new Rect();
64
65 /**
66 * During layout, the current screen borders accounting for any currently visible system UI
67 * elements.
68 */
69 public final Rect mSystem = new Rect();
70
71 /** For applications requesting stable content insets, these are them. */
72 public final Rect mStable = new Rect();
73
74 /**
75 * For applications requesting stable content insets but have also set the fullscreen window
76 * flag, these are the stable dimensions without the status bar.
77 */
78 public final Rect mStableFullscreen = new Rect();
79
80 /**
81 * During layout, the current screen borders with all outer decoration (status bar, input method
82 * dock) accounted for.
83 */
84 public final Rect mCurrent = new Rect();
85
86 /**
87 * During layout, the frame in which content should be displayed to the user, accounting for all
88 * screen decoration except for any space they deem as available for other content. This is
89 * usually the same as mCurrent*, but may be larger if the screen decor has supplied content
90 * insets.
91 */
92 public final Rect mContent = new Rect();
93
94 /**
95 * During layout, the frame in which voice content should be displayed to the user, accounting
96 * for all screen decoration except for any space they deem as available for other content.
97 */
98 public final Rect mVoiceContent = new Rect();
99
100 /** During layout, the current screen borders along which input method windows are placed. */
101 public final Rect mDock = new Rect();
102
Adrian Roos5c6b6222017-11-07 17:36:10 +0100103 /** Definition of the cutout */
104 @NonNull public DisplayCutout mDisplayCutout = DisplayCutout.NO_CUTOUT;
105
106 /**
107 * During layout, the frame that is display-cutout safe, i.e. that does not intersect with it.
108 */
109 public final Rect mDisplayCutoutSafe = new Rect();
110
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000111 private final Rect mDisplayInfoOverscan = new Rect();
112 private final Rect mRotatedDisplayInfoOverscan = new Rect();
113 public int mDisplayWidth;
114 public int mDisplayHeight;
115
116 public int mRotation;
117
118 public DisplayFrames(int displayId, DisplayInfo info) {
119 mDisplayId = displayId;
120 onDisplayInfoUpdated(info);
121 }
122
123 public void onDisplayInfoUpdated(DisplayInfo info) {
124 mDisplayWidth = info.logicalWidth;
125 mDisplayHeight = info.logicalHeight;
126 mRotation = info.rotation;
127 mDisplayInfoOverscan.set(
128 info.overscanLeft, info.overscanTop, info.overscanRight, info.overscanBottom);
129 }
130
Adrian Roos000cf5e2017-11-10 15:55:18 +0100131 public void onBeginLayout(boolean emulateDisplayCutout, int statusBarHeight) {
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000132 switch (mRotation) {
133 case ROTATION_90:
134 mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.top;
135 mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.right;
136 mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.bottom;
137 mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.left;
138 break;
139 case ROTATION_180:
140 mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.right;
141 mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.bottom;
142 mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.left;
143 mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.top;
144 break;
145 case ROTATION_270:
146 mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.bottom;
147 mRotatedDisplayInfoOverscan.top = mDisplayInfoOverscan.left;
148 mRotatedDisplayInfoOverscan.right = mDisplayInfoOverscan.top;
149 mRotatedDisplayInfoOverscan.bottom = mDisplayInfoOverscan.right;
150 break;
151 default:
152 mRotatedDisplayInfoOverscan.set(mDisplayInfoOverscan);
153 break;
154 }
155
156 mRestrictedOverscan.set(0, 0, mDisplayWidth, mDisplayHeight);
157 mOverscan.set(mRestrictedOverscan);
158 mSystem.set(mRestrictedOverscan);
159 mUnrestricted.set(mRotatedDisplayInfoOverscan);
160 mUnrestricted.right = mDisplayWidth - mUnrestricted.right;
161 mUnrestricted.bottom = mDisplayHeight - mUnrestricted.bottom;
162 mRestricted.set(mUnrestricted);
163 mDock.set(mUnrestricted);
164 mContent.set(mUnrestricted);
165 mVoiceContent.set(mUnrestricted);
166 mStable.set(mUnrestricted);
167 mStableFullscreen.set(mUnrestricted);
168 mCurrent.set(mUnrestricted);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100169 mDisplayCutout = DisplayCutout.NO_CUTOUT;
170 mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
171 Integer.MAX_VALUE, Integer.MAX_VALUE);
Adrian Roos000cf5e2017-11-10 15:55:18 +0100172 if (emulateDisplayCutout) {
173 setEmulatedDisplayCutout((int) (statusBarHeight * 0.8));
174 }
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000175 }
176
177 public int getInputMethodWindowVisibleHeight() {
178 return mDock.bottom - mCurrent.bottom;
179 }
180
Adrian Roos000cf5e2017-11-10 15:55:18 +0100181 private void setEmulatedDisplayCutout(int height) {
182 final boolean swappedDimensions = mRotation == ROTATION_90 || mRotation == ROTATION_270;
183
184 final int screenWidth = swappedDimensions ? mDisplayHeight : mDisplayWidth;
185 final int screenHeight = swappedDimensions ? mDisplayWidth : mDisplayHeight;
186
187 final int widthTop = (int) (screenWidth * 0.3);
188 final int widthBottom = widthTop - height;
189
190 switch (mRotation) {
191 case ROTATION_90:
192 mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
193 new Point(0, (screenWidth - widthTop) / 2),
194 new Point(height, (screenWidth - widthBottom) / 2),
195 new Point(height, (screenWidth + widthBottom) / 2),
196 new Point(0, (screenWidth + widthTop) / 2)
197 )).calculateRelativeTo(mUnrestricted);
198 mDisplayCutoutSafe.left = height;
199 break;
200 case ROTATION_180:
201 mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
202 new Point((screenWidth - widthTop) / 2, screenHeight),
203 new Point((screenWidth - widthBottom) / 2, screenHeight - height),
204 new Point((screenWidth + widthBottom) / 2, screenHeight - height),
205 new Point((screenWidth + widthTop) / 2, screenHeight)
206 )).calculateRelativeTo(mUnrestricted);
207 mDisplayCutoutSafe.bottom = screenHeight - height;
208 break;
209 case ROTATION_270:
210 mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
211 new Point(screenHeight, (screenWidth - widthTop) / 2),
212 new Point(screenHeight - height, (screenWidth - widthBottom) / 2),
213 new Point(screenHeight - height, (screenWidth + widthBottom) / 2),
214 new Point(screenHeight, (screenWidth + widthTop) / 2)
215 )).calculateRelativeTo(mUnrestricted);
216 mDisplayCutoutSafe.right = screenHeight - height;
217 break;
218 default:
219 mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList(
220 new Point((screenWidth - widthTop) / 2, 0),
221 new Point((screenWidth - widthBottom) / 2, height),
222 new Point((screenWidth + widthBottom) / 2, height),
223 new Point((screenWidth + widthTop) / 2, 0)
224 )).calculateRelativeTo(mUnrestricted);
225 mDisplayCutoutSafe.top = height;
226 break;
227 }
228 }
229
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000230 public void writeToProto(ProtoOutputStream proto, long fieldId) {
231 final long token = proto.start(fieldId);
232 mStable.writeToProto(proto, STABLE_BOUNDS);
233 proto.end(token);
234 }
235
236 public void dump(String prefix, PrintWriter pw) {
237 pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight
238 + " r=" + mRotation);
239 final String myPrefix = prefix + " ";
240 dumpFrame(mStable, "mStable", myPrefix, pw);
241 dumpFrame(mStableFullscreen, "mStableFullscreen", myPrefix, pw);
242 dumpFrame(mDock, "mDock", myPrefix, pw);
243 dumpFrame(mCurrent, "mCurrent", myPrefix, pw);
244 dumpFrame(mSystem, "mSystem", myPrefix, pw);
245 dumpFrame(mContent, "mContent", myPrefix, pw);
246 dumpFrame(mVoiceContent, "mVoiceContent", myPrefix, pw);
247 dumpFrame(mOverscan, "mOverscan", myPrefix, pw);
248 dumpFrame(mRestrictedOverscan, "mRestrictedOverscan", myPrefix, pw);
249 dumpFrame(mRestricted, "mRestricted", myPrefix, pw);
250 dumpFrame(mUnrestricted, "mUnrestricted", myPrefix, pw);
251 dumpFrame(mDisplayInfoOverscan, "mDisplayInfoOverscan", myPrefix, pw);
252 dumpFrame(mRotatedDisplayInfoOverscan, "mRotatedDisplayInfoOverscan", myPrefix, pw);
Adrian Roos5c6b6222017-11-07 17:36:10 +0100253 pw.println(myPrefix + "mDisplayCutout=" + mDisplayCutout);
Wale Ogunwale828ff7e2017-11-14 01:01:29 +0000254 }
255
256 private void dumpFrame(Rect frame, String name, String prefix, PrintWriter pw) {
257 pw.print(prefix + name + "="); frame.printShortString(pw); pw.println();
258 }
259}