blob: 46566e79d99cc9988e926764108e2355e527e891 [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
Wale Ogunwale6cbbc9a2017-09-06 19:01:03 -070019import static android.app.ActivityThread.isSystem;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070020import static android.app.WindowConfigurationProto.ACTIVITY_TYPE;
21import static android.app.WindowConfigurationProto.APP_BOUNDS;
22import static android.app.WindowConfigurationProto.WINDOWING_MODE;
Wale Ogunwale6cbbc9a2017-09-06 19:01:03 -070023
Wale Ogunwale822e5122017-07-26 06:02:24 -070024import android.annotation.IntDef;
25import android.annotation.NonNull;
Steven Timotiuse597ca12017-09-05 15:46:29 -070026import android.annotation.TestApi;
Wale Ogunwale822e5122017-07-26 06:02:24 -070027import android.content.res.Configuration;
28import android.graphics.Rect;
29import android.os.Parcel;
30import android.os.Parcelable;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070031import android.util.proto.ProtoOutputStream;
Wale Ogunwale822e5122017-07-26 06:02:24 -070032import android.view.DisplayInfo;
33
Wale Ogunwale822e5122017-07-26 06:02:24 -070034/**
35 * Class that contains windowing configuration/state for other objects that contain windows directly
36 * or indirectly. E.g. Activities, Task, Displays, ...
37 * The test class is {@link com.android.server.wm.WindowConfigurationTests} which must be kept
38 * up-to-date and ran anytime changes are made to this class.
39 * @hide
40 */
Steven Timotiuse597ca12017-09-05 15:46:29 -070041@TestApi
Wale Ogunwale822e5122017-07-26 06:02:24 -070042public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {
Bryce Leef3c6a472017-11-14 14:53:06 -080043 /**
44 * bounds that can differ from app bounds, which may include things such as insets.
45 *
46 * TODO: Investigate combining with {@link mAppBounds}. Can the latter be a product of the
47 * former?
48 */
49 private Rect mBounds = new Rect();
Wale Ogunwale822e5122017-07-26 06:02:24 -070050
51 /**
52 * {@link android.graphics.Rect} defining app bounds. The dimensions override usages of
53 * {@link DisplayInfo#appHeight} and {@link DisplayInfo#appWidth} and mirrors these values at
54 * the display level. Lower levels can override these values to provide custom bounds to enforce
55 * features such as a max aspect ratio.
56 */
57 private Rect mAppBounds;
58
Wale Ogunwale687b4272017-07-27 02:56:23 -070059 /** The current windowing mode of the configuration. */
60 private @WindowingMode int mWindowingMode;
61
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070062 /** Windowing mode is currently not defined. */
Wale Ogunwale687b4272017-07-27 02:56:23 -070063 public static final int WINDOWING_MODE_UNDEFINED = 0;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070064 /** Occupies the full area of the screen or the parent container. */
Wale Ogunwale687b4272017-07-27 02:56:23 -070065 public static final int WINDOWING_MODE_FULLSCREEN = 1;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070066 /** Always on-top (always visible). of other siblings in its parent container. */
Wale Ogunwale687b4272017-07-27 02:56:23 -070067 public static final int WINDOWING_MODE_PINNED = 2;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070068 /** The primary container driving the screen to be in split-screen mode. */
Wale Ogunwale926aade2017-08-29 11:24:37 -070069 public static final int WINDOWING_MODE_SPLIT_SCREEN_PRIMARY = 3;
70 /**
71 * The containers adjacent to the {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} container in
72 * split-screen mode.
Wale Ogunwale0568aed2017-09-08 13:29:37 -070073 * NOTE: Containers launched with the windowing mode with APIs like
74 * {@link ActivityOptions#setLaunchWindowingMode(int)} will be launched in
75 * {@link #WINDOWING_MODE_FULLSCREEN} if the display isn't currently in split-screen windowing
76 * mode
77 * @see #WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY
Wale Ogunwale926aade2017-08-29 11:24:37 -070078 */
79 public static final int WINDOWING_MODE_SPLIT_SCREEN_SECONDARY = 4;
Wale Ogunwale0568aed2017-09-08 13:29:37 -070080 /**
81 * Alias for {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} that makes it clear that the usage
82 * points for APIs like {@link ActivityOptions#setLaunchWindowingMode(int)} that the container
83 * will launch into fullscreen or split-screen secondary depending on if the device is currently
84 * in fullscreen mode or split-screen mode.
85 */
86 public static final int WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY =
87 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070088 /** Can be freely resized within its parent container. */
Wale Ogunwale926aade2017-08-29 11:24:37 -070089 public static final int WINDOWING_MODE_FREEFORM = 5;
Wale Ogunwale687b4272017-07-27 02:56:23 -070090
Steven Timotiuse597ca12017-09-05 15:46:29 -070091 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -070092 @IntDef(prefix = { "WINDOWING_MODE_" }, value = {
Wale Ogunwale687b4272017-07-27 02:56:23 -070093 WINDOWING_MODE_UNDEFINED,
94 WINDOWING_MODE_FULLSCREEN,
95 WINDOWING_MODE_PINNED,
Wale Ogunwale926aade2017-08-29 11:24:37 -070096 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
97 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
Wale Ogunwale0568aed2017-09-08 13:29:37 -070098 WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY,
Wale Ogunwale687b4272017-07-27 02:56:23 -070099 WINDOWING_MODE_FREEFORM,
100 })
Wale Ogunwale687b4272017-07-27 02:56:23 -0700101 public @interface WindowingMode {}
Wale Ogunwale822e5122017-07-26 06:02:24 -0700102
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700103 /** The current activity type of the configuration. */
104 private @ActivityType int mActivityType;
105
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700106 /** Activity type is currently not defined. */
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700107 public static final int ACTIVITY_TYPE_UNDEFINED = 0;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700108 /** Standard activity type. Nothing special about the activity... */
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700109 public static final int ACTIVITY_TYPE_STANDARD = 1;
110 /** Home/Launcher activity type. */
111 public static final int ACTIVITY_TYPE_HOME = 2;
Winson Chung3f0e59a2017-10-25 10:19:05 -0700112 /** Recents/Overview activity type. There is only one activity with this type in the system. */
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700113 public static final int ACTIVITY_TYPE_RECENTS = 3;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700114 /** Assistant activity type. */
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700115 public static final int ACTIVITY_TYPE_ASSISTANT = 4;
116
Steven Timotiuse597ca12017-09-05 15:46:29 -0700117 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700118 @IntDef(prefix = { "ACTIVITY_TYPE_" }, value = {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700119 ACTIVITY_TYPE_UNDEFINED,
120 ACTIVITY_TYPE_STANDARD,
121 ACTIVITY_TYPE_HOME,
122 ACTIVITY_TYPE_RECENTS,
123 ACTIVITY_TYPE_ASSISTANT,
124 })
125 public @interface ActivityType {}
126
Bryce Leef3c6a472017-11-14 14:53:06 -0800127 /** Bit that indicates that the {@link #mBounds} changed.
128 * @hide */
129 public static final int WINDOW_CONFIG_BOUNDS = 1 << 0;
Steven Timotiuse597ca12017-09-05 15:46:29 -0700130 /** Bit that indicates that the {@link #mAppBounds} changed.
131 * @hide */
Bryce Leef3c6a472017-11-14 14:53:06 -0800132 public static final int WINDOW_CONFIG_APP_BOUNDS = 1 << 1;
Steven Timotiuse597ca12017-09-05 15:46:29 -0700133 /** Bit that indicates that the {@link #mWindowingMode} changed.
134 * @hide */
Bryce Leef3c6a472017-11-14 14:53:06 -0800135 public static final int WINDOW_CONFIG_WINDOWING_MODE = 1 << 2;
Steven Timotiuse597ca12017-09-05 15:46:29 -0700136 /** Bit that indicates that the {@link #mActivityType} changed.
137 * @hide */
Bryce Leef3c6a472017-11-14 14:53:06 -0800138 public static final int WINDOW_CONFIG_ACTIVITY_TYPE = 1 << 3;
Wale Ogunwale687b4272017-07-27 02:56:23 -0700139
Steven Timotiuse597ca12017-09-05 15:46:29 -0700140 /** @hide */
Jeff Sharkeyce8db992017-12-13 20:05:05 -0700141 @IntDef(flag = true, prefix = { "WINDOW_CONFIG_" }, value = {
142 WINDOW_CONFIG_BOUNDS,
143 WINDOW_CONFIG_APP_BOUNDS,
144 WINDOW_CONFIG_WINDOWING_MODE,
145 WINDOW_CONFIG_ACTIVITY_TYPE
146 })
Wale Ogunwale687b4272017-07-27 02:56:23 -0700147 public @interface WindowConfig {}
Wale Ogunwale822e5122017-07-26 06:02:24 -0700148
Robert Carr32bcb102018-01-29 15:03:23 -0800149 /** @hide */
150 public static final int PINNED_WINDOWING_MODE_ELEVATION_IN_DIP = 5;
151
Wale Ogunwale822e5122017-07-26 06:02:24 -0700152 public WindowConfiguration() {
153 unset();
154 }
155
Steven Timotiuse597ca12017-09-05 15:46:29 -0700156 /** @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700157 public WindowConfiguration(WindowConfiguration configuration) {
158 setTo(configuration);
159 }
160
161 private WindowConfiguration(Parcel in) {
162 readFromParcel(in);
163 }
164
165 @Override
166 public void writeToParcel(Parcel dest, int flags) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800167 dest.writeParcelable(mBounds, flags);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700168 dest.writeParcelable(mAppBounds, flags);
Wale Ogunwale687b4272017-07-27 02:56:23 -0700169 dest.writeInt(mWindowingMode);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700170 dest.writeInt(mActivityType);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700171 }
172
173 private void readFromParcel(Parcel source) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800174 mBounds = source.readParcelable(Rect.class.getClassLoader());
Wale Ogunwale822e5122017-07-26 06:02:24 -0700175 mAppBounds = source.readParcelable(Rect.class.getClassLoader());
Wale Ogunwale687b4272017-07-27 02:56:23 -0700176 mWindowingMode = source.readInt();
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700177 mActivityType = source.readInt();
Wale Ogunwale822e5122017-07-26 06:02:24 -0700178 }
179
180 @Override
181 public int describeContents() {
182 return 0;
183 }
184
Steven Timotiuse597ca12017-09-05 15:46:29 -0700185 /** @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700186 public static final Creator<WindowConfiguration> CREATOR = new Creator<WindowConfiguration>() {
187 @Override
188 public WindowConfiguration createFromParcel(Parcel in) {
189 return new WindowConfiguration(in);
190 }
191
192 @Override
193 public WindowConfiguration[] newArray(int size) {
194 return new WindowConfiguration[size];
195 }
196 };
197
198 /**
Bryce Leef3c6a472017-11-14 14:53:06 -0800199 * Sets the bounds to the provided {@link Rect}.
200 * @param rect the new bounds value.
201 */
202 public void setBounds(Rect rect) {
203 if (rect == null) {
204 mBounds.setEmpty();
205 return;
206 }
207
208 mBounds.set(rect);
209 }
210
211 /**
Wale Ogunwale822e5122017-07-26 06:02:24 -0700212 * Set {@link #mAppBounds} to the input Rect.
213 * @param rect The rect value to set {@link #mAppBounds} to.
214 * @see #getAppBounds()
215 */
216 public void setAppBounds(Rect rect) {
217 if (rect == null) {
218 mAppBounds = null;
219 return;
220 }
221
222 setAppBounds(rect.left, rect.top, rect.right, rect.bottom);
223 }
224
225 /**
226 * @see #setAppBounds(Rect)
227 * @see #getAppBounds()
Steven Timotiuse597ca12017-09-05 15:46:29 -0700228 * @hide
Wale Ogunwale822e5122017-07-26 06:02:24 -0700229 */
230 public void setAppBounds(int left, int top, int right, int bottom) {
231 if (mAppBounds == null) {
232 mAppBounds = new Rect();
233 }
234
235 mAppBounds.set(left, top, right, bottom);
236 }
237
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700238 /** @see #setAppBounds(Rect) */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700239 public Rect getAppBounds() {
240 return mAppBounds;
241 }
242
Bryce Leef3c6a472017-11-14 14:53:06 -0800243 /** @see #setBounds(Rect) */
244 public Rect getBounds() {
245 return mBounds;
246 }
247
Wale Ogunwale687b4272017-07-27 02:56:23 -0700248 public void setWindowingMode(@WindowingMode int windowingMode) {
249 mWindowingMode = windowingMode;
250 }
251
252 @WindowingMode
253 public int getWindowingMode() {
254 return mWindowingMode;
255 }
256
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700257 public void setActivityType(@ActivityType int activityType) {
258 if (mActivityType == activityType) {
259 return;
260 }
Wale Ogunwale6cbbc9a2017-09-06 19:01:03 -0700261
262 // Error check within system server that we are not changing activity type which can be
263 // dangerous. It is okay for things to change in the application process as it doesn't
264 // affect how other things is the system is managed.
265 if (isSystem()
266 && mActivityType != ACTIVITY_TYPE_UNDEFINED
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700267 && activityType != ACTIVITY_TYPE_UNDEFINED) {
268 throw new IllegalStateException("Can't change activity type once set: " + this
269 + " activityType=" + activityTypeToString(activityType));
270 }
271 mActivityType = activityType;
272 }
273
274 @ActivityType
275 public int getActivityType() {
276 return mActivityType;
277 }
278
Wale Ogunwale822e5122017-07-26 06:02:24 -0700279 public void setTo(WindowConfiguration other) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800280 setBounds(other.mBounds);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700281 setAppBounds(other.mAppBounds);
Wale Ogunwale687b4272017-07-27 02:56:23 -0700282 setWindowingMode(other.mWindowingMode);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700283 setActivityType(other.mActivityType);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700284 }
285
Steven Timotiuse597ca12017-09-05 15:46:29 -0700286 /** Set this object to completely undefined.
287 * @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700288 public void unset() {
289 setToDefaults();
290 }
291
Steven Timotiuse597ca12017-09-05 15:46:29 -0700292 /** @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700293 public void setToDefaults() {
294 setAppBounds(null);
Bryce Leef3c6a472017-11-14 14:53:06 -0800295 setBounds(null);
Wale Ogunwale687b4272017-07-27 02:56:23 -0700296 setWindowingMode(WINDOWING_MODE_UNDEFINED);
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700297 setActivityType(ACTIVITY_TYPE_UNDEFINED);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700298 }
299
300 /**
301 * Copies the fields from delta into this Configuration object, keeping
302 * track of which ones have changed. Any undefined fields in {@code delta}
303 * are ignored and not copied in to the current Configuration.
304 *
305 * @return a bit mask of the changed fields, as per {@link #diff}
Steven Timotiuse597ca12017-09-05 15:46:29 -0700306 * @hide
Wale Ogunwale822e5122017-07-26 06:02:24 -0700307 */
308 public @WindowConfig int updateFrom(@NonNull WindowConfiguration delta) {
309 int changed = 0;
Bryce Leef3c6a472017-11-14 14:53:06 -0800310 // Only allow override if bounds is not empty
311 if (!delta.mBounds.isEmpty() && !delta.mBounds.equals(mBounds)) {
312 changed |= WINDOW_CONFIG_BOUNDS;
313 setBounds(delta.mBounds);
314 }
Wale Ogunwale822e5122017-07-26 06:02:24 -0700315 if (delta.mAppBounds != null && !delta.mAppBounds.equals(mAppBounds)) {
316 changed |= WINDOW_CONFIG_APP_BOUNDS;
317 setAppBounds(delta.mAppBounds);
318 }
Wale Ogunwale687b4272017-07-27 02:56:23 -0700319 if (delta.mWindowingMode != WINDOWING_MODE_UNDEFINED
320 && mWindowingMode != delta.mWindowingMode) {
321 changed |= WINDOW_CONFIG_WINDOWING_MODE;
322 setWindowingMode(delta.mWindowingMode);
323 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700324 if (delta.mActivityType != ACTIVITY_TYPE_UNDEFINED
325 && mActivityType != delta.mActivityType) {
326 changed |= WINDOW_CONFIG_ACTIVITY_TYPE;
327 setActivityType(delta.mActivityType);
328 }
Wale Ogunwale822e5122017-07-26 06:02:24 -0700329 return changed;
330 }
331
332 /**
333 * Return a bit mask of the differences between this Configuration object and the given one.
334 * Does not change the values of either. Any undefined fields in <var>other</var> are ignored.
335 * @param other The configuration to diff against.
336 * @param compareUndefined If undefined values should be compared.
337 * @return Returns a bit mask indicating which configuration
338 * values has changed, containing any combination of {@link WindowConfig} flags.
339 *
340 * @see Configuration#diff(Configuration)
Steven Timotiuse597ca12017-09-05 15:46:29 -0700341 * @hide
Wale Ogunwale822e5122017-07-26 06:02:24 -0700342 */
343 public @WindowConfig long diff(WindowConfiguration other, boolean compareUndefined) {
344 long changes = 0;
345
Bryce Leef3c6a472017-11-14 14:53:06 -0800346 if (!mBounds.equals(other.mBounds)) {
347 changes |= WINDOW_CONFIG_BOUNDS;
348 }
349
Wale Ogunwale822e5122017-07-26 06:02:24 -0700350 // Make sure that one of the values is not null and that they are not equal.
351 if ((compareUndefined || other.mAppBounds != null)
352 && mAppBounds != other.mAppBounds
353 && (mAppBounds == null || !mAppBounds.equals(other.mAppBounds))) {
354 changes |= WINDOW_CONFIG_APP_BOUNDS;
355 }
356
Wale Ogunwale687b4272017-07-27 02:56:23 -0700357 if ((compareUndefined || other.mWindowingMode != WINDOWING_MODE_UNDEFINED)
358 && mWindowingMode != other.mWindowingMode) {
359 changes |= WINDOW_CONFIG_WINDOWING_MODE;
360 }
361
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700362 if ((compareUndefined || other.mActivityType != ACTIVITY_TYPE_UNDEFINED)
363 && mActivityType != other.mActivityType) {
364 changes |= WINDOW_CONFIG_ACTIVITY_TYPE;
365 }
366
Wale Ogunwale822e5122017-07-26 06:02:24 -0700367 return changes;
368 }
369
370 @Override
371 public int compareTo(WindowConfiguration that) {
372 int n = 0;
373 if (mAppBounds == null && that.mAppBounds != null) {
374 return 1;
375 } else if (mAppBounds != null && that.mAppBounds == null) {
376 return -1;
377 } else if (mAppBounds != null && that.mAppBounds != null) {
378 n = mAppBounds.left - that.mAppBounds.left;
379 if (n != 0) return n;
380 n = mAppBounds.top - that.mAppBounds.top;
381 if (n != 0) return n;
382 n = mAppBounds.right - that.mAppBounds.right;
383 if (n != 0) return n;
384 n = mAppBounds.bottom - that.mAppBounds.bottom;
385 if (n != 0) return n;
386 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800387
388 n = mBounds.left - that.mBounds.left;
389 if (n != 0) return n;
390 n = mBounds.top - that.mBounds.top;
391 if (n != 0) return n;
392 n = mBounds.right - that.mBounds.right;
393 if (n != 0) return n;
394 n = mBounds.bottom - that.mBounds.bottom;
395 if (n != 0) return n;
396
Wale Ogunwale687b4272017-07-27 02:56:23 -0700397 n = mWindowingMode - that.mWindowingMode;
398 if (n != 0) return n;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700399 n = mActivityType - that.mActivityType;
400 if (n != 0) return n;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700401
402 // if (n != 0) return n;
403 return n;
404 }
405
Steven Timotiuse597ca12017-09-05 15:46:29 -0700406 /** @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700407 @Override
408 public boolean equals(Object that) {
409 if (that == null) return false;
410 if (that == this) return true;
411 if (!(that instanceof WindowConfiguration)) {
412 return false;
413 }
414 return this.compareTo((WindowConfiguration) that) == 0;
415 }
416
Steven Timotiuse597ca12017-09-05 15:46:29 -0700417 /** @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700418 @Override
419 public int hashCode() {
420 int result = 0;
421 if (mAppBounds != null) {
422 result = 31 * result + mAppBounds.hashCode();
423 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800424 result = 31 * result + mBounds.hashCode();
425
Wale Ogunwale687b4272017-07-27 02:56:23 -0700426 result = 31 * result + mWindowingMode;
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700427 result = 31 * result + mActivityType;
Wale Ogunwale822e5122017-07-26 06:02:24 -0700428 return result;
429 }
430
Steven Timotiuse597ca12017-09-05 15:46:29 -0700431 /** @hide */
Wale Ogunwale822e5122017-07-26 06:02:24 -0700432 @Override
433 public String toString() {
Bryce Leef3c6a472017-11-14 14:53:06 -0800434 return "{ mBounds=" + mBounds
435 + " mAppBounds=" + mAppBounds
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700436 + " mWindowingMode=" + windowingModeToString(mWindowingMode)
437 + " mActivityType=" + activityTypeToString(mActivityType) + "}";
Wale Ogunwale687b4272017-07-27 02:56:23 -0700438 }
439
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700440 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700441 * Write to a protocol buffer output stream.
442 * Protocol buffer message definition at {@link android.app.WindowConfigurationProto}
443 *
444 * @param protoOutputStream Stream to write the WindowConfiguration object to.
445 * @param fieldId Field Id of the WindowConfiguration as defined in the parent message
446 * @hide
447 */
448 public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
449 final long token = protoOutputStream.start(fieldId);
450 if (mAppBounds != null) {
451 mAppBounds.writeToProto(protoOutputStream, APP_BOUNDS);
452 }
453 protoOutputStream.write(WINDOWING_MODE, mWindowingMode);
454 protoOutputStream.write(ACTIVITY_TYPE, mActivityType);
455 protoOutputStream.end(token);
456 }
457
458 /**
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700459 * Returns true if the activities associated with this window configuration display a shadow
460 * around their border.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700461 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700462 */
463 public boolean hasWindowShadow() {
464 return tasksAreFloating();
465 }
466
467 /**
468 * Returns true if the activities associated with this window configuration display a decor
469 * view.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700470 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700471 */
472 public boolean hasWindowDecorCaption() {
473 return mWindowingMode == WINDOWING_MODE_FREEFORM;
474 }
475
476 /**
477 * Returns true if the tasks associated with this window configuration can be resized
478 * independently of their parent container.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700479 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700480 */
481 public boolean canResizeTask() {
482 return mWindowingMode == WINDOWING_MODE_FREEFORM;
483 }
484
Steven Timotiuse597ca12017-09-05 15:46:29 -0700485 /** Returns true if the task bounds should persist across power cycles.
486 * @hide */
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700487 public boolean persistTaskBounds() {
488 return mWindowingMode == WINDOWING_MODE_FREEFORM;
489 }
490
491 /**
492 * Returns true if the tasks associated with this window configuration are floating.
493 * Floating tasks are laid out differently as they are allowed to extend past the display bounds
494 * without overscan insets.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700495 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700496 */
497 public boolean tasksAreFloating() {
498 return mWindowingMode == WINDOWING_MODE_FREEFORM || mWindowingMode == WINDOWING_MODE_PINNED;
499 }
500
501 /**
502 * Returns true if the windows associated with this window configuration can receive input keys.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700503 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700504 */
505 public boolean canReceiveKeys() {
506 return mWindowingMode != WINDOWING_MODE_PINNED;
507 }
508
509 /**
510 * Returns true if the container associated with this window configuration is always-on-top of
511 * its siblings.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700512 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700513 */
514 public boolean isAlwaysOnTop() {
515 return mWindowingMode == WINDOWING_MODE_PINNED;
516 }
517
518 /**
519 * Returns true if any visible windows belonging to apps with this window configuration should
520 * be kept on screen when the app is killed due to something like the low memory killer.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700521 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700522 */
523 public boolean keepVisibleDeadAppWindowOnScreen() {
524 return mWindowingMode != WINDOWING_MODE_PINNED;
525 }
526
527 /**
528 * Returns true if the backdrop on the client side should match the frame of the window.
529 * Returns false, if the backdrop should be fullscreen.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700530 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700531 */
532 public boolean useWindowFrameForBackdrop() {
533 return mWindowingMode == WINDOWING_MODE_FREEFORM || mWindowingMode == WINDOWING_MODE_PINNED;
534 }
535
536 /**
537 * Returns true if this container may be scaled without resizing, and windows within may need
538 * to be configured as such.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700539 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700540 */
541 public boolean windowsAreScaleable() {
542 return mWindowingMode == WINDOWING_MODE_PINNED;
543 }
544
545 /**
546 * Returns true if windows in this container should be given move animations by default.
Steven Timotiuse597ca12017-09-05 15:46:29 -0700547 * @hide
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700548 */
549 public boolean hasMovementAnimations() {
Jorim Jaggibb6ee9b2017-09-06 23:59:34 +0200550 return mWindowingMode != WINDOWING_MODE_PINNED;
Wale Ogunwale3382ab12017-07-27 08:55:03 -0700551 }
552
Wale Ogunwale926aade2017-08-29 11:24:37 -0700553 /**
554 * Returns true if this container can be put in either
555 * {@link #WINDOWING_MODE_SPLIT_SCREEN_PRIMARY} or
556 * {@link #WINDOWING_MODE_SPLIT_SCREEN_SECONDARY} windowing modes based on its current state.
557 * @hide
558 */
559 public boolean supportSplitScreenWindowingMode() {
Wale Ogunwale2b07da82017-11-08 14:52:40 -0800560 return supportSplitScreenWindowingMode(mActivityType);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700561 }
562
563 /** @hide */
Wale Ogunwale2b07da82017-11-08 14:52:40 -0800564 public static boolean supportSplitScreenWindowingMode(int activityType) {
565 return activityType != ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale926aade2017-08-29 11:24:37 -0700566 }
567
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700568 /** @hide */
569 public static String windowingModeToString(@WindowingMode int windowingMode) {
Wale Ogunwale687b4272017-07-27 02:56:23 -0700570 switch (windowingMode) {
571 case WINDOWING_MODE_UNDEFINED: return "undefined";
572 case WINDOWING_MODE_FULLSCREEN: return "fullscreen";
573 case WINDOWING_MODE_PINNED: return "pinned";
Wale Ogunwale926aade2017-08-29 11:24:37 -0700574 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return "split-screen-primary";
575 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return "split-screen-secondary";
Wale Ogunwale687b4272017-07-27 02:56:23 -0700576 case WINDOWING_MODE_FREEFORM: return "freeform";
577 }
578 return String.valueOf(windowingMode);
Wale Ogunwale822e5122017-07-26 06:02:24 -0700579 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700580
Steven Timotiuse597ca12017-09-05 15:46:29 -0700581 /** @hide */
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700582 public static String activityTypeToString(@ActivityType int applicationType) {
583 switch (applicationType) {
584 case ACTIVITY_TYPE_UNDEFINED: return "undefined";
585 case ACTIVITY_TYPE_STANDARD: return "standard";
586 case ACTIVITY_TYPE_HOME: return "home";
587 case ACTIVITY_TYPE_RECENTS: return "recents";
588 case ACTIVITY_TYPE_ASSISTANT: return "assistant";
589 }
590 return String.valueOf(applicationType);
591 }
Wale Ogunwale822e5122017-07-26 06:02:24 -0700592}