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