1 /*
2  * Copyright (C) 2018 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 com.android.server.wm.WindowFramesProto.COMPAT_FRAME;
20 import static com.android.server.wm.WindowFramesProto.CONTAINING_FRAME;
21 import static com.android.server.wm.WindowFramesProto.DISPLAY_FRAME;
22 import static com.android.server.wm.WindowFramesProto.FRAME;
23 import static com.android.server.wm.WindowFramesProto.PARENT_FRAME;
24 
25 import android.annotation.NonNull;
26 import android.graphics.Rect;
27 import android.util.proto.ProtoOutputStream;
28 
29 import java.io.PrintWriter;
30 
31 /**
32  * Container class for all the window frames that affect how windows are laid out.
33  *
34  * TODO(b/111611553): Investigate which frames are still needed and which are duplicates
35  */
36 public class WindowFrames {
37     private static final StringBuilder sTmpSB = new StringBuilder();
38 
39     /**
40      * In most cases, this is the area of the entire screen.
41      *
42      * TODO(b/111611553): The name is unclear and most likely should be swapped with
43      * {@link #mDisplayFrame}
44      * TODO(b/111611553): In some cases, it also includes top insets, like for IME. Determine
45      * whether this is still necessary to do.
46      */
47     public final Rect mParentFrame = new Rect();
48 
49     /**
50      * The entire screen area of the {@link Task} this window is in. Usually equal to the
51      * screen area of the device.
52      *
53      * TODO(b/111611553): The name is unclear and most likely should be swapped with
54      * {@link #mParentFrame}
55      */
56     public final Rect mDisplayFrame = new Rect();
57 
58     /**
59      * Similar to {@link #mDisplayFrame}
60      *
61      * TODO: Why is this different than mDisplayFrame
62      */
63     final Rect mContainingFrame = new Rect();
64 
65     /**
66      * "Real" frame that the application sees, in display coordinate space.
67      */
68     final Rect mFrame = new Rect();
69 
70     /**
71      * The last real frame that was reported to the client.
72      */
73     final Rect mLastFrame = new Rect();
74 
75     /**
76      * mFrame but relative to the parent container.
77      */
78     final Rect mRelFrame = new Rect();
79 
80     /**
81      * mLastFrame but relative to the parent container
82      */
83     final Rect mLastRelFrame = new Rect();
84 
85     private boolean mFrameSizeChanged = false;
86 
87     // Frame that is scaled to the application's coordinate space when in
88     // screen size compatibility mode.
89     final Rect mCompatFrame = new Rect();
90 
91     /**
92      * {@code true} if the window frame is a simulated frame and attached to a decor window.
93      */
94     boolean mIsSimulatingDecorWindow = false;
95 
96     /**
97      * Whether the parent frame would have been different if there was no display cutout.
98      */
99     private boolean mParentFrameWasClippedByDisplayCutout;
100 
101     boolean mLastForceReportingResized = false;
102     boolean mForceReportingResized = false;
103 
104     private boolean mContentChanged;
105 
setFrames(Rect parentFrame, Rect displayFrame)106     public void setFrames(Rect parentFrame, Rect displayFrame) {
107         mParentFrame.set(parentFrame);
108         mDisplayFrame.set(displayFrame);
109     }
110 
setParentFrameWasClippedByDisplayCutout( boolean parentFrameWasClippedByDisplayCutout)111     public void setParentFrameWasClippedByDisplayCutout(
112             boolean parentFrameWasClippedByDisplayCutout) {
113         mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;
114     }
115 
parentFrameWasClippedByDisplayCutout()116     boolean parentFrameWasClippedByDisplayCutout() {
117         return mParentFrameWasClippedByDisplayCutout;
118     }
119 
120     /**
121      * @return true if the width or height has changed since last updating resizing window.
122      */
didFrameSizeChange()123     boolean didFrameSizeChange() {
124         return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
125     }
126 
offsetFrames(int layoutXDiff, int layoutYDiff)127     void offsetFrames(int layoutXDiff, int layoutYDiff) {
128         mFrame.offset(layoutXDiff, layoutYDiff);
129     }
130 
131     /**
132      * Updates info about whether the size of the window has changed since last reported.
133      *
134      * @return true if info about size has changed since last reported.
135      */
setReportResizeHints()136     boolean setReportResizeHints() {
137         mLastForceReportingResized |= mForceReportingResized;
138         mFrameSizeChanged |= didFrameSizeChange();
139         return mLastForceReportingResized || mFrameSizeChanged;
140     }
141 
142     /**
143      * @return true if the width or height has changed since last reported to the client.
144      */
isFrameSizeChangeReported()145     boolean isFrameSizeChangeReported() {
146         return mFrameSizeChanged || didFrameSizeChange();
147     }
148 
149     /**
150      * Resets the size changed flags so they're all set to false again. This should be called
151      * after the frames are reported to client.
152      */
clearReportResizeHints()153     void clearReportResizeHints() {
154         mLastForceReportingResized = false;
155         mFrameSizeChanged = false;
156     }
157 
158     /**
159      * Clears factors that would cause report-resize.
160      */
onResizeHandled()161     void onResizeHandled() {
162         mForceReportingResized = false;
163     }
164 
165     /**
166      * Forces the next layout pass to update the client.
167      */
forceReportingResized()168     void forceReportingResized() {
169         mForceReportingResized = true;
170     }
171 
172     /**
173      * Sets whether the content has changed. This means that either the size or parent frame has
174      * changed.
175      */
setContentChanged(boolean contentChanged)176     public void setContentChanged(boolean contentChanged) {
177         mContentChanged = contentChanged;
178     }
179 
180     /**
181      * @see #setContentChanged(boolean)
182      */
hasContentChanged()183     boolean hasContentChanged() {
184         return mContentChanged;
185     }
186 
dumpDebug(@onNull ProtoOutputStream proto, long fieldId)187     public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) {
188         final long token = proto.start(fieldId);
189         mParentFrame.dumpDebug(proto, PARENT_FRAME);
190         mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME);
191         mContainingFrame.dumpDebug(proto, CONTAINING_FRAME);
192         mFrame.dumpDebug(proto, FRAME);
193         mCompatFrame.dumpDebug(proto, COMPAT_FRAME);
194         proto.end(token);
195     }
196 
dump(PrintWriter pw, String prefix)197     public void dump(PrintWriter pw, String prefix) {
198         pw.println(prefix + "Frames: containing="
199                 + mContainingFrame.toShortString(sTmpSB)
200                 + " parent=" + mParentFrame.toShortString(sTmpSB)
201                 + " display=" + mDisplayFrame.toShortString(sTmpSB));
202         pw.println(prefix + "mFrame=" + mFrame.toShortString(sTmpSB)
203                 + " last=" + mLastFrame.toShortString(sTmpSB));
204     }
205 
getInsetsChangedInfo()206     String getInsetsChangedInfo() {
207         return "forceReportingResized=" + mLastForceReportingResized;
208     }
209 }
210