blob: e4ec8c3b3b9cb6db8f0933b77ad5d25f60df6f00 [file] [log] [blame]
Wale Ogunwale822e5122017-07-26 06:02:24 -07001/*
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
17package android.app;
18
19import android.annotation.IntDef;
20import android.annotation.NonNull;
21import android.content.res.Configuration;
22import android.graphics.Rect;
23import android.os.Parcel;
24import android.os.Parcelable;
25import android.view.DisplayInfo;
26
27import java.lang.annotation.Retention;
28import java.lang.annotation.RetentionPolicy;
29
30/**
31 * Class that contains windowing configuration/state for other objects that contain windows directly
32 * or indirectly. E.g. Activities, Task, Displays, ...
33 * The test class is {@link com.android.server.wm.WindowConfigurationTests} which must be kept
34 * up-to-date and ran anytime changes are made to this class.
35 * @hide
36 */
37public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {
38
39 /**
40 * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
41 * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
42 * the display level. Lower levels can override these values to provide custom bounds to enforce
43 * features such as a max aspect ratio.
44 */
45 private Rect mAppBounds;
46
Wale Ogunwale687b4272017-07-27 02:56:23 -070047 /** The current windowing mode of the configuration. */
48 private @WindowingMode int mWindowingMode;
49
50 /** Windowing mode is currently not defined. */
51 public static final int WINDOWING_MODE_UNDEFINED = 0;
52 /** Occupies the full area of the screen or the parent container. */
53 public static final int WINDOWING_MODE_FULLSCREEN = 1;
54 /** Always on-top (always visible). of other siblings in its parent container. */
55 public static final int WINDOWING_MODE_PINNED = 2;
56 /** Occupies a dedicated region of the screen or its parent container. */
57 public static final int WINDOWING_MODE_DOCKED = 3;
58 /** Can be freely resized within its parent container. */
59 public static final int WINDOWING_MODE_FREEFORM = 4;
60
61 @IntDef(value = {
62 WINDOWING_MODE_UNDEFINED,
63 WINDOWING_MODE_FULLSCREEN,
64 WINDOWING_MODE_PINNED,
65 WINDOWING_MODE_DOCKED,
66 WINDOWING_MODE_FREEFORM,
67 })
Wale Ogunwale822e5122017-07-26 06:02:24 -070068 @Retention(RetentionPolicy.SOURCE)
Wale Ogunwale687b4272017-07-27 02:56:23 -070069 public @interface WindowingMode {}
Wale Ogunwale822e5122017-07-26 06:02:24 -070070
71 /** Bit that indicates that the {@link #mAppBounds} changed. */
72 public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 0;
Wale Ogunwale687b4272017-07-27 02:56:23 -070073 /** Bit that indicates that the {@link #mWindowingMode} changed. */
74 public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 1;
75
76 @IntDef(flag = true,
77 value = {
78 WINDOW_CONFIG_APP_BOUNDS,
79 WINDOW_CONFIG_WINDOWING_MODE,
80 })
81 @Retention(RetentionPolicy.SOURCE)
82 public @interface WindowConfig {}
Wale Ogunwale822e5122017-07-26 06:02:24 -070083
84 public WindowConfiguration() {
85 unset();
86 }
87
88 public WindowConfiguration(WindowConfiguration configuration) {
89 setTo(configuration);
90 }
91
92 private WindowConfiguration(Parcel in) {
93 readFromParcel(in);
94 }
95
96 @Override
97 public void writeToParcel(Parcel dest, int flags) {
98 dest.writeParcelable(mAppBounds, flags);
Wale Ogunwale687b4272017-07-27 02:56:23 -070099 dest.writeInt(mWindowingMode);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700100 }
101
102 private void readFromParcel(Parcel source) {
103 mAppBounds = source.readParcelable(Rect.class.getClassLoader());
Wale Ogunwale687b4272017-07-27 02:56:23 -0700104 mWindowingMode = source.readInt();
Wale Ogunwale822e5122017-07-26 06:02:24 -0700105 }
106
107 @Override
108 public int describeContents() {
109 return 0;
110 }
111
112 public static final Creator<WindowConfiguration> CREATOR = new Creator<WindowConfiguration>() {
113 @Override
114 public WindowConfiguration createFromParcel(Parcel in) {
115 return new WindowConfiguration(in);
116 }
117
118 @Override
119 public WindowConfiguration[] newArray(int size) {
120 return new WindowConfiguration[size];
121 }
122 };
123
124 /**
125 * Set {@link #mAppBounds} to the input Rect.
126 * @param rect The rect value to set {@link #mAppBounds} to.
127 * @see #getAppBounds()
128 */
129 public void setAppBounds(Rect rect) {
130 if (rect == null) {
131 mAppBounds = null;
132 return;
133 }
134
135 setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
136 }
137
138 /**
139 * @see #setAppBounds(Rect)
140 * @see #getAppBounds()
141 */
142 public void setAppBounds(int left, int top, int right, int bottom) {
143 if (mAppBounds == null) {
144 mAppBounds = new Rect();
145 }
146
147 mAppBounds.set(left, top, right, bottom);
148 }
149
150 /**
151 * @see #setAppBounds(Rect)
152 */
153 public Rect getAppBounds() {
154 return mAppBounds;
155 }
156
Wale Ogunwale687b4272017-07-27 02:56:23 -0700157 public void setWindowingMode(@WindowingMode int windowingMode) {
158 mWindowingMode = windowingMode;
159 }
160
161 @WindowingMode
162 public int getWindowingMode() {
163 return mWindowingMode;
164 }
165
Wale Ogunwale822e5122017-07-26 06:02:24 -0700166 public void setTo(WindowConfiguration other) {
167 setAppBounds(other.mAppBounds);
Wale Ogunwale687b4272017-07-27 02:56:23 -0700168 setWindowingMode(other.mWindowingMode);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700169 }
170
171 /** Set this object to completely undefined. */
172 public void unset() {
173 setToDefaults();
174 }
175
176 public void setToDefaults() {
177 setAppBounds(null);
Wale Ogunwale687b4272017-07-27 02:56:23 -0700178 setWindowingMode(WINDOWING_MODE_UNDEFINED);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700179 }
180
181 /**
182 * Copies the fields from delta into this Configuration object, keeping
183 * track of which ones have changed. Any undefined fields in {@code delta}
184 * are ignored and not copied in to the current Configuration.
185 *
186 * @return a bit mask of the changed fields, as per {@link #diff}
187 */
188 public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) {
189 int changed = 0;
190 if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) {
191 changed |= WINDOW_CONFIG_APP_BOUNDS;
192 setAppBounds(delta.mAppBounds);
193 }
Wale Ogunwale687b4272017-07-27 02:56:23 -0700194 if (delta.mWindowingMode != WINDOWING_MODE_UNDEFINED
195 && mWindowingMode != delta.mWindowingMode) {
196 changed |= WINDOW_CONFIG_WINDOWING_MODE;
197 setWindowingMode(delta.mWindowingMode);
198 }
Wale Ogunwale822e5122017-07-26 06:02:24 -0700199 return changed;
200 }
201
202 /**
203 * Return a bit mask of the differences between this Configuration object and the given one.
204 * Does not change the values of either. Any undefined fields in <var>other</var> are ignored.
205 * @param other The configuration to diff against.
206 * @param compareUndefined If undefined values should be compared.
207 * @return Returns a bit mask indicating which configuration
208 * values has changed, containing any combination of {@link WindowConfig} flags.
209 *
210 * @see Configuration#diff(Configuration)
211 */
212 public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) {
213 long changes = 0;
214
215 // Make sure that one of the values is not null and that they are not equal.
216 if ((compareUndefined || other.mAppBounds != null)
217 && mAppBounds != other.mAppBounds
218 && (mAppBounds == null || !mAppBounds.equals(other.mAppBounds))) {
219 changes |= WINDOW_CONFIG_APP_BOUNDS;
220 }
221
Wale Ogunwale687b4272017-07-27 02:56:23 -0700222 if ((compareUndefined || other.mWindowingMode != WINDOWING_MODE_UNDEFINED)
223 && mWindowingMode != other.mWindowingMode) {
224 changes |= WINDOW_CONFIG_WINDOWING_MODE;
225 }
226
Wale Ogunwale822e5122017-07-26 06:02:24 -0700227 return changes;
228 }
229
230 @Override
231 public int compareTo(WindowConfiguration that) {
232 int n = 0;
233 if (mAppBounds == null && that.mAppBounds != null) {
234 return 1;
235 } else if (mAppBounds != null && that.mAppBounds == null) {
236 return -1;
237 } else if (mAppBounds != null && that.mAppBounds != null) {
238 n = mAppBounds.left - that.mAppBounds.left;
239 if (n != 0) return n;
240 n = mAppBounds.top - that.mAppBounds.top;
241 if (n != 0) return n;
242 n = mAppBounds.right - that.mAppBounds.right;
243 if (n != 0) return n;
244 n = mAppBounds.bottom - that.mAppBounds.bottom;
245 if (n != 0) return n;
246 }
Wale Ogunwale687b4272017-07-27 02:56:23 -0700247 n = mWindowingMode - that.mWindowingMode;
248 if (n != 0) return n;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700249
250 // if (n != 0) return n;
251 return n;
252 }
253
254 @Override
255 public boolean equals(Object that) {
256 if (that == null) return false;
257 if (that == this) return true;
258 if (!(that instanceof WindowConfiguration)) {
259 return false;
260 }
261 return this.compareTo((WindowConfiguration) that) == 0;
262 }
263
264 @Override
265 public int hashCode() {
266 int result = 0;
267 if (mAppBounds != null) {
268 result = 31 * result + mAppBounds.hashCode();
269 }
Wale Ogunwale687b4272017-07-27 02:56:23 -0700270 result = 31 * result + mWindowingMode;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700271 return result;
272 }
273
274 @Override
275 public String toString() {
Wale Ogunwale687b4272017-07-27 02:56:23 -0700276 return "{mAppBounds=" + mAppBounds
277 + " mWindowingMode=" + windowingModeToString(mWindowingMode) + "}";
278 }
279
280 private static String windowingModeToString(@WindowingMode int windowingMode) {
281 switch (windowingMode) {
282 case WINDOWING_MODE_UNDEFINED: return "undefined";
283 case WINDOWING_MODE_FULLSCREEN: return "fullscreen";
284 case WINDOWING_MODE_PINNED: return "pinned";
285 case WINDOWING_MODE_DOCKED: return "docked";
286 case WINDOWING_MODE_FREEFORM: return "freeform";
287 }
288 return String.valueOf(windowingMode);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700289 }
290}