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 last real frame that was reported to the client.
55      */
56     final Rect mLastFrame = new Rect();
57 
58     /**
59      * mFrame but relative to the parent container.
60      */
61     final Rect mRelFrame = new Rect();
62 
63     /**
64      * mLastFrame but relative to the parent container
65      */
66     final Rect mLastRelFrame = new Rect();
67 
68     private boolean mFrameSizeChanged = false;
69 
70     // Frame that is scaled to the application's coordinate space when in
71     // screen size compatibility mode.
72     final Rect mCompatFrame = new Rect();
73 
74     /**
75      * Whether the parent frame would have been different if there was no display cutout.
76      */
77     private boolean mParentFrameWasClippedByDisplayCutout;
78 
79     boolean mLastForceReportingResized = false;
80     boolean mForceReportingResized = false;
81 
82     private boolean mContentChanged;
83 
84     private boolean mInsetsChanged;
85 
setFrames(Rect parentFrame, Rect displayFrame)86     public void setFrames(Rect parentFrame, Rect displayFrame) {
87         mParentFrame.set(parentFrame);
88         mDisplayFrame.set(displayFrame);
89     }
90 
setParentFrameWasClippedByDisplayCutout( boolean parentFrameWasClippedByDisplayCutout)91     public void setParentFrameWasClippedByDisplayCutout(
92             boolean parentFrameWasClippedByDisplayCutout) {
93         mParentFrameWasClippedByDisplayCutout = parentFrameWasClippedByDisplayCutout;
94     }
95 
parentFrameWasClippedByDisplayCutout()96     boolean parentFrameWasClippedByDisplayCutout() {
97         return mParentFrameWasClippedByDisplayCutout;
98     }
99 
100     /**
101      * @return true if the width or height has changed since last updating resizing window.
102      */
didFrameSizeChange()103     boolean didFrameSizeChange() {
104         return (mLastFrame.width() != mFrame.width()) || (mLastFrame.height() != mFrame.height());
105     }
106 
107     /**
108      * Updates info about whether the size of the window has changed since last reported.
109      *
110      * @return true if info about size has changed since last reported.
111      */
setReportResizeHints()112     boolean setReportResizeHints() {
113         mLastForceReportingResized |= mForceReportingResized;
114         mFrameSizeChanged |= didFrameSizeChange();
115         return mLastForceReportingResized || mFrameSizeChanged;
116     }
117 
118     /**
119      * @return true if the width or height has changed since last reported to the client.
120      */
isFrameSizeChangeReported()121     boolean isFrameSizeChangeReported() {
122         return mFrameSizeChanged || didFrameSizeChange();
123     }
124 
125     /**
126      * Resets the size changed flags so they're all set to false again. This should be called
127      * after the frames are reported to client.
128      */
clearReportResizeHints()129     void clearReportResizeHints() {
130         mLastForceReportingResized = false;
131         mFrameSizeChanged = false;
132     }
133 
134     /**
135      * Clears factors that would cause report-resize.
136      */
onResizeHandled()137     void onResizeHandled() {
138         mForceReportingResized = false;
139     }
140 
141     /**
142      * Forces the next layout pass to update the client.
143      */
forceReportingResized()144     void forceReportingResized() {
145         mForceReportingResized = true;
146     }
147 
148     /**
149      * Sets whether the content has changed. This means that either the size or parent frame has
150      * changed.
151      */
setContentChanged(boolean contentChanged)152     public void setContentChanged(boolean contentChanged) {
153         mContentChanged = contentChanged;
154     }
155 
156     /**
157      * @see #setContentChanged(boolean)
158      */
hasContentChanged()159     boolean hasContentChanged() {
160         return mContentChanged;
161     }
162 
163     /**
164      * Sets whether we need to report {@link android.view.InsetsState} to the client.
165      */
setInsetsChanged(boolean insetsChanged)166     void setInsetsChanged(boolean insetsChanged) {
167         mInsetsChanged = insetsChanged;
168     }
169 
170     /**
171      * @see #setInsetsChanged(boolean)
172      */
hasInsetsChanged()173     boolean hasInsetsChanged() {
174         return mInsetsChanged;
175     }
176 
dumpDebug(@onNull ProtoOutputStream proto, long fieldId)177     public void dumpDebug(@NonNull ProtoOutputStream proto, long fieldId) {
178         final long token = proto.start(fieldId);
179         mParentFrame.dumpDebug(proto, PARENT_FRAME);
180         mDisplayFrame.dumpDebug(proto, DISPLAY_FRAME);
181         mFrame.dumpDebug(proto, FRAME);
182         mCompatFrame.dumpDebug(proto, COMPAT_FRAME);
183         proto.end(token);
184     }
185 
dump(PrintWriter pw, String prefix)186     public void dump(PrintWriter pw, String prefix) {
187         pw.println(prefix + "Frames: parent=" + mParentFrame.toShortString(sTmpSB)
188                 + " display=" + mDisplayFrame.toShortString(sTmpSB)
189                 + " frame=" + mFrame.toShortString(sTmpSB)
190                 + " last=" + mLastFrame.toShortString(sTmpSB)
191                 + " insetsChanged=" + mInsetsChanged);
192     }
193 
getInsetsChangedInfo()194     String getInsetsChangedInfo() {
195         return "forceReportingResized=" + mLastForceReportingResized
196                 + " insetsChanged=" + mInsetsChanged;
197     }
198 }
199