1 /*
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
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.view.Surface.ROTATION_180;
20 import static android.view.Surface.ROTATION_270;
21 import static android.view.Surface.ROTATION_90;
22 import static com.android.server.wm.DisplayFramesProto.STABLE_BOUNDS;
23 
24 import android.annotation.NonNull;
25 import android.graphics.Rect;
26 import android.util.proto.ProtoOutputStream;
27 import android.view.DisplayCutout;
28 import android.view.DisplayInfo;
29 
30 import com.android.server.wm.utils.WmDisplayCutout;
31 
32 import java.io.PrintWriter;
33 
34 /**
35  * Container class for all the display frames that affect how we do window layout on a display.
36  * @hide
37  */
38 public class DisplayFrames {
39     public final int mDisplayId;
40 
41     /**
42      * The current visible size of the screen; really; (ir)regardless of whether the status bar can
43      * be hidden but not extending into the overscan area.
44      */
45     public final Rect mUnrestricted = new Rect();
46 
47     /**
48      * The current size of the screen; these may be different than (0,0)-(dw,dh) if the status bar
49      * can't be hidden; in that case it effectively carves out that area of the display from all
50      * other windows.
51      */
52     public final Rect mRestricted = new Rect();
53 
54     /**
55      * During layout, the current screen borders accounting for any currently visible system UI
56      * elements.
57      */
58     public final Rect mSystem = new Rect();
59 
60     /** For applications requesting stable content insets, these are them. */
61     public final Rect mStable = new Rect();
62 
63     /**
64      * For applications requesting stable content insets but have also set the fullscreen window
65      * flag, these are the stable dimensions without the status bar.
66      */
67     public final Rect mStableFullscreen = new Rect();
68 
69     /**
70      * During layout, the current screen borders with all outer decoration (status bar, input method
71      * dock) accounted for.
72      */
73     public final Rect mCurrent = new Rect();
74 
75     /**
76      * During layout, the frame in which content should be displayed to the user, accounting for all
77      * screen decoration except for any space they deem as available for other content. This is
78      * usually the same as mCurrent*, but may be larger if the screen decor has supplied content
79      * insets.
80      */
81     public final Rect mContent = new Rect();
82 
83     /**
84      * During layout, the frame in which voice content should be displayed to the user, accounting
85      * for all screen decoration except for any space they deem as available for other content.
86      */
87     public final Rect mVoiceContent = new Rect();
88 
89     /** During layout, the current screen borders along which input method windows are placed. */
90     public final Rect mDock = new Rect();
91 
92     /** The display cutout used for layout (after rotation) */
93     @NonNull public WmDisplayCutout mDisplayCutout = WmDisplayCutout.NO_CUTOUT;
94 
95     /** The cutout as supplied by display info */
96     @NonNull public WmDisplayCutout mDisplayInfoCutout = WmDisplayCutout.NO_CUTOUT;
97 
98     /**
99      * During layout, the frame that is display-cutout safe, i.e. that does not intersect with it.
100      */
101     public final Rect mDisplayCutoutSafe = new Rect();
102 
103     public int mDisplayWidth;
104     public int mDisplayHeight;
105 
106     public int mRotation;
107 
DisplayFrames(int displayId, DisplayInfo info, WmDisplayCutout displayCutout)108     public DisplayFrames(int displayId, DisplayInfo info, WmDisplayCutout displayCutout) {
109         mDisplayId = displayId;
110         onDisplayInfoUpdated(info, displayCutout);
111     }
112 
onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout)113     public void onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout) {
114         mDisplayWidth = info.logicalWidth;
115         mDisplayHeight = info.logicalHeight;
116         mRotation = info.rotation;
117         mDisplayInfoCutout = displayCutout != null ? displayCutout : WmDisplayCutout.NO_CUTOUT;
118     }
119 
onBeginLayout()120     public void onBeginLayout() {
121         mUnrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
122         mRestricted.set(mUnrestricted);
123         mSystem.set(mUnrestricted);
124         mDock.set(mUnrestricted);
125         mContent.set(mUnrestricted);
126         mVoiceContent.set(mUnrestricted);
127         mStable.set(mUnrestricted);
128         mStableFullscreen.set(mUnrestricted);
129         mCurrent.set(mUnrestricted);
130 
131         mDisplayCutout = mDisplayInfoCutout;
132         mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE,
133                 Integer.MAX_VALUE, Integer.MAX_VALUE);
134         if (!mDisplayCutout.getDisplayCutout().isEmpty()) {
135             final DisplayCutout c = mDisplayCutout.getDisplayCutout();
136             if (c.getSafeInsetLeft() > 0) {
137                 mDisplayCutoutSafe.left = mUnrestricted.left + c.getSafeInsetLeft();
138             }
139             if (c.getSafeInsetTop() > 0) {
140                 mDisplayCutoutSafe.top = mUnrestricted.top + c.getSafeInsetTop();
141             }
142             if (c.getSafeInsetRight() > 0) {
143                 mDisplayCutoutSafe.right = mUnrestricted.right - c.getSafeInsetRight();
144             }
145             if (c.getSafeInsetBottom() > 0) {
146                 mDisplayCutoutSafe.bottom = mUnrestricted.bottom - c.getSafeInsetBottom();
147             }
148         }
149     }
150 
getInputMethodWindowVisibleHeight()151     public int getInputMethodWindowVisibleHeight() {
152         return mDock.bottom - mCurrent.bottom;
153     }
154 
dumpDebug(ProtoOutputStream proto, long fieldId)155     public void dumpDebug(ProtoOutputStream proto, long fieldId) {
156         final long token = proto.start(fieldId);
157         mStable.dumpDebug(proto, STABLE_BOUNDS);
158         proto.end(token);
159     }
160 
dump(String prefix, PrintWriter pw)161     public void dump(String prefix, PrintWriter pw) {
162         pw.println(prefix + "DisplayFrames w=" + mDisplayWidth + " h=" + mDisplayHeight
163                 + " r=" + mRotation);
164         final String myPrefix = prefix + "  ";
165         dumpFrame(mStable, "mStable", myPrefix, pw);
166         dumpFrame(mStableFullscreen, "mStableFullscreen", myPrefix, pw);
167         dumpFrame(mDock, "mDock", myPrefix, pw);
168         dumpFrame(mCurrent, "mCurrent", myPrefix, pw);
169         dumpFrame(mSystem, "mSystem", myPrefix, pw);
170         dumpFrame(mContent, "mContent", myPrefix, pw);
171         dumpFrame(mVoiceContent, "mVoiceContent", myPrefix, pw);
172         dumpFrame(mRestricted, "mRestricted", myPrefix, pw);
173         dumpFrame(mUnrestricted, "mUnrestricted", myPrefix, pw);
174         pw.println(myPrefix + "mDisplayCutout=" + mDisplayCutout);
175     }
176 
dumpFrame(Rect frame, String name, String prefix, PrintWriter pw)177     private void dumpFrame(Rect frame, String name, String prefix, PrintWriter pw) {
178         pw.print(prefix + name + "="); frame.printShortString(pw); pw.println();
179     }
180 }
181