blob: 7b4281c61f1295d1e4cba41e1398d56681f96a32 [file] [log] [blame]
Craig Mautnerc00204b2013-03-05 15:02:14 -08001/*
2 * Copyright (C) 2013 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 com.android.server.wm;
18
Matthew Ngbf155872017-10-27 15:24:39 -070019import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
20import static android.app.ActivityManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
Wale Ogunwale68278562017-09-23 17:13:55 -070021import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
22import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
24import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale51362492016-09-08 17:49:17 -070025import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070026import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
27import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Winson Chung303c6b72016-10-24 17:12:49 -070028import static android.view.Display.DEFAULT_DISPLAY;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070029import static android.view.WindowManager.DOCKED_BOTTOM;
30import static android.view.WindowManager.DOCKED_INVALID;
31import static android.view.WindowManager.DOCKED_LEFT;
32import static android.view.WindowManager.DOCKED_RIGHT;
33import static android.view.WindowManager.DOCKED_TOP;
chaviwe07246a2017-12-12 16:18:29 -080034
Jorim Jaggiff71d202016-04-14 13:12:36 -070035import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070036import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
37import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Steven Timotiusaf03df62017-07-18 16:56:43 -070038import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
39import static com.android.server.wm.proto.StackProto.BOUNDS;
40import static com.android.server.wm.proto.StackProto.FILLS_PARENT;
41import static com.android.server.wm.proto.StackProto.ID;
42import static com.android.server.wm.proto.StackProto.TASKS;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070043import static com.android.server.wm.proto.StackProto.WINDOW_CONTAINER;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070044
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070045import android.annotation.CallSuper;
Wale Ogunwale60454db2015-01-23 16:05:07 -080046import android.content.res.Configuration;
Jorim Jaggi1e8c4c82018-01-09 15:14:15 +010047import android.graphics.Point;
Craig Mautner05d29032013-05-03 13:40:13 -070048import android.graphics.Rect;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -070049import android.graphics.Region;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080050import android.os.RemoteException;
Craig Mautner2c2549c2013-11-12 08:31:15 -080051import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070052import android.util.Slog;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070053import android.util.SparseArray;
Steven Timotiusaf03df62017-07-18 16:56:43 -070054import android.util.proto.ProtoOutputStream;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070055import android.view.DisplayInfo;
Wale Ogunwale94744212015-09-21 19:01:47 -070056import android.view.Surface;
Robert Carrf59b8dd2017-10-02 18:58:36 -070057import android.view.SurfaceControl;
Filip Gruszczynski54977fe2015-10-19 17:26:45 -070058
Jorim Jaggi737af722015-12-31 10:42:27 +010059import com.android.internal.policy.DividerSnapAlgorithm;
60import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
61import com.android.internal.policy.DockedDividerUtils;
Craig Mautner2c2549c2013-11-12 08:31:15 -080062import com.android.server.EventLogTags;
Craig Mautner05d29032013-05-03 13:40:13 -070063
Craig Mautner00af9fe2013-03-25 09:13:41 -070064import java.io.PrintWriter;
Craig Mautnerc00204b2013-03-05 15:02:14 -080065
Robert Carrf59b8dd2017-10-02 18:58:36 -070066public class TaskStack extends WindowContainer<Task> implements
Winson Chung8bca9e42017-04-16 15:59:43 -070067 BoundsAnimationTarget {
Chong Zhang198afac2016-04-15 12:03:11 -070068 /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
69 * restrict IME adjustment so that a min portion of top stack remains visible.*/
70 private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
71
72 /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
73 private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070074
Craig Mautner00af9fe2013-03-25 09:13:41 -070075 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080076 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070077
78 /** The display this stack sits under. */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -070079 // TODO: Track parent marks like this in WindowContainer.
Craig Mautnerdf88d732014-01-27 09:21:32 -080080 private DisplayContent mDisplayContent;
Craig Mautner00af9fe2013-03-25 09:13:41 -070081
Craig Mautnerb660b9d2014-02-13 10:59:16 -080082 /** For comparison with DisplayContent bounds. */
83 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070084 private Rect mTmpRect2 = new Rect();
Winson Chung19953ca2017-04-11 11:19:23 -070085 private Rect mTmpRect3 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -080086
Chong Zhangb816b862016-01-25 12:01:12 -080087 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
88 private final Rect mAdjustedBounds = new Rect();
89
Jorim Jaggieb88d832016-04-13 20:17:43 -070090 /**
91 * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
92 * represent the state when the animation has ended.
93 */
94 private final Rect mFullyAdjustedImeBounds = new Rect();
95
Wale Ogunwale94744212015-09-21 19:01:47 -070096 // Device rotation as of the last time {@link #mBounds} was set.
Wale Ogunwale02319a62016-09-26 15:21:22 -070097 private int mRotation;
Wale Ogunwale94744212015-09-21 19:01:47 -070098
Jorim Jaggi11c62e12016-04-05 20:41:21 -070099 /** Density as of last time {@link #mBounds} was set. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700100 private int mDensity;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700101
Robert Carrf59b8dd2017-10-02 18:58:36 -0700102 private SurfaceControl mAnimationBackgroundSurface;
103 private boolean mAnimationBackgroundSurfaceIsShown = false;
Craig Mautner05d29032013-05-03 13:40:13 -0700104
105 /** The particular window with an Animation with non-zero background color. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700106 private WindowStateAnimator mAnimationBackgroundAnimator;
Craig Mautner05d29032013-05-03 13:40:13 -0700107
Craig Mautnerdc548482014-02-05 13:35:24 -0800108 /** Application tokens that are exiting, but still on screen for animations. */
109 final AppTokenList mExitingAppTokens = new AppTokenList();
Wale Ogunwale48458e12017-06-06 10:07:58 -0700110 final AppTokenList mTmpAppTokens = new AppTokenList();
Craig Mautnerdc548482014-02-05 13:35:24 -0800111
Craig Mautner95da1082014-02-24 17:54:35 -0800112 /** Detach this stack from its display when animation completes. */
Wale Ogunwalef6192862016-09-10 13:42:30 -0700113 // TODO: maybe tie this to WindowContainer#removeChild some how...
Wale Ogunwale10124582016-09-15 20:25:50 -0700114 boolean mDeferRemoval;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800115
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800116 private final Rect mTmpAdjustedBounds = new Rect();
117 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700118 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800119 private WindowState mImeWin;
120 private float mMinimizeAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700121 private float mAdjustImeAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700122 private float mAdjustDividerAmount;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800123 private final int mDockedStackMinimizeThickness;
124
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700125 // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
126 // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
127 // would otherwise apply while resizing, while resizing in the bounds animating mode.
Robert Carr1ca6a332016-04-11 18:00:43 -0700128 private boolean mBoundsAnimating = false;
Winson Chung40a5f932017-04-13 16:39:36 -0700129 // Set when an animation has been requested but has not yet started from the UI thread. This is
130 // cleared when the animation actually starts.
131 private boolean mBoundsAnimatingRequested = false;
Robert Carr7e4c90e2017-02-15 19:52:38 -0800132 private boolean mBoundsAnimatingToFullscreen = false;
Winson Chung19953ca2017-04-11 11:19:23 -0700133 private boolean mCancelCurrentBoundsAnimation = false;
Winson Chung84a38342016-11-08 16:15:10 -0800134 private Rect mBoundsAnimationTarget = new Rect();
Winson Chung8bca9e42017-04-16 15:59:43 -0700135 private Rect mBoundsAnimationSourceHintBounds = new Rect();
Robert Carr0d00c2e2016-02-29 17:45:02 -0800136
Chong Zhang167bbfac2016-03-31 09:44:34 -0700137 // Temporary storage for the new bounds that should be used after the configuration change.
138 // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
139 private final Rect mBoundsAfterRotation = new Rect();
140
Robert Carr18f622f2017-05-08 11:20:43 -0700141 Rect mPreAnimationBounds = new Rect();
142
Robert Carrf59b8dd2017-10-02 18:58:36 -0700143 private Dimmer mDimmer = new Dimmer(this);
144
145 /**
146 * For {@link #prepareSurfaces}.
147 */
148 final Rect mTmpDimBoundsRect = new Rect();
Jorim Jaggi1e8c4c82018-01-09 15:14:15 +0100149 private final Point mLastSurfaceSize = new Point();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700150
Wale Ogunwale704a3c02017-09-18 15:30:52 -0700151 TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100152 super(service);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800153 mStackId = stackId;
Wale Ogunwale704a3c02017-09-18 15:30:52 -0700154 setController(controller);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800155 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
156 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700157 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800158 }
159
160 DisplayContent getDisplayContent() {
161 return mDisplayContent;
162 }
163
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700164 Task findHomeTask() {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700165 if (!isActivityTypeHome() || mChildren.isEmpty()) {
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700166 return null;
167 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700168 return mChildren.get(mChildren.size() - 1);
Wale Ogunwale15ead902016-09-02 14:30:11 -0700169 }
170
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700171 /**
172 * Set the bounds of the stack and its containing tasks.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700173 * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700174 * @param taskBounds Bounds for individual tasks, keyed by task id.
Bryce Leef3c6a472017-11-14 14:53:06 -0800175 * @param taskTempInsetBounds Inset bounds for individual tasks, keyed by task id.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700176 * @return True if the stack bounds was changed.
177 * */
Wale Ogunwalea6e902e2015-09-21 18:37:15 -0700178 boolean setBounds(
Bryce Leef3c6a472017-11-14 14:53:06 -0800179 Rect stackBounds, SparseArray<Rect> taskBounds, SparseArray<Rect> taskTempInsetBounds) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500180 setBounds(stackBounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700181
182 // Update bounds of containing tasks.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700183 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
184 final Task task = mChildren.get(taskNdx);
Bryce Leef3c6a472017-11-14 14:53:06 -0800185 task.setBounds(taskBounds.get(task.mTaskId), false /* forced */);
186 task.setTempInsetBounds(taskTempInsetBounds != null ?
187 taskTempInsetBounds.get(task.mTaskId) : null);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700188 }
189 return true;
190 }
191
Jorim Jaggi0429f352015-12-22 16:29:16 +0100192 void prepareFreezingTaskBounds() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700193 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
194 final Task task = mChildren.get(taskNdx);
Jorim Jaggi0429f352015-12-22 16:29:16 +0100195 task.prepareFreezingBounds();
196 }
197 }
198
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800199 /**
200 * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
201 * the normal task bounds.
202 *
203 * @param bounds The adjusted bounds.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800204 */
Jorim Jaggieb88d832016-04-13 20:17:43 -0700205 private void setAdjustedBounds(Rect bounds) {
206 if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
207 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800208 }
209
210 mAdjustedBounds.set(bounds);
211 final boolean adjusted = !mAdjustedBounds.isEmpty();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700212 Rect insetBounds = null;
Matthew Nge15352e2016-12-20 15:36:29 -0800213 if (adjusted && isAdjustedForMinimizedDockedStack()) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800214 insetBounds = getRawBounds();
Chong Zhang5117e272016-05-03 12:47:34 -0700215 } else if (adjusted && mAdjustedForIme) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700216 if (mImeGoingAway) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800217 insetBounds = getRawBounds();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700218 } else {
219 insetBounds = mFullyAdjustedImeBounds;
220 }
221 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800222 alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : getRawBounds(), insetBounds);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700223 mDisplayContent.setLayoutNeeded();
chaviwe07246a2017-12-12 16:18:29 -0800224
225 updateSurfaceBounds();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800226 }
227
228 private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800229 if (matchParentBounds()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800230 return;
231 }
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700232
233 final boolean alignBottom = mAdjustedForIme && getDockSide() == DOCKED_TOP;
234
Chong Zhangb816b862016-01-25 12:01:12 -0800235 // Update bounds of containing tasks.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700236 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
237 final Task task = mChildren.get(taskNdx);
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700238 task.alignToAdjustedBounds(adjustedBounds, tempInsetBounds, alignBottom);
Chong Zhangb816b862016-01-25 12:01:12 -0800239 }
240 }
241
Bryce Leef3c6a472017-11-14 14:53:06 -0800242 private void updateAnimationBackgroundBounds() {
Robert Carrf59b8dd2017-10-02 18:58:36 -0700243 if (mAnimationBackgroundSurface == null) {
244 return;
245 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800246 getRawBounds(mTmpRect);
chaviwe07246a2017-12-12 16:18:29 -0800247 final Rect stackBounds = getBounds();
248 getPendingTransaction()
249 .setSize(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
250 .setPosition(mAnimationBackgroundSurface, mTmpRect.left - stackBounds.left,
251 mTmpRect.top - stackBounds.top);
Robert Carrf59b8dd2017-10-02 18:58:36 -0700252 scheduleAnimation();
253 }
254
255 private void hideAnimationSurface() {
256 if (mAnimationBackgroundSurface == null) {
257 return;
258 }
259 getPendingTransaction().hide(mAnimationBackgroundSurface);
260 mAnimationBackgroundSurfaceIsShown = false;
261 scheduleAnimation();
262 }
263
264 private void showAnimationSurface(float alpha) {
265 if (mAnimationBackgroundSurface == null) {
266 return;
267 }
268 getPendingTransaction().setLayer(mAnimationBackgroundSurface, Integer.MIN_VALUE)
269 .setAlpha(mAnimationBackgroundSurface, alpha)
270 .show(mAnimationBackgroundSurface);
271 mAnimationBackgroundSurfaceIsShown = true;
272 scheduleAnimation();
273 }
274
Bryce Leef3c6a472017-11-14 14:53:06 -0800275 @Override
276 public int setBounds(Rect bounds) {
277 return setBounds(getOverrideBounds(), bounds);
278 }
279
280 private int setBounds(Rect existing, Rect bounds) {
Wale Ogunwale94744212015-09-21 19:01:47 -0700281 int rotation = Surface.ROTATION_0;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700282 int density = DENSITY_DPI_UNDEFINED;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800283 if (mDisplayContent != null) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800284 mDisplayContent.getBounds(mTmpRect);
Wale Ogunwale94744212015-09-21 19:01:47 -0700285 rotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700286 density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800287 }
288
Bryce Leef3c6a472017-11-14 14:53:06 -0800289 if (equivalentBounds(existing, bounds) && mRotation == rotation) {
290 return BOUNDS_CHANGE_NONE;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800291 }
292
Bryce Leef3c6a472017-11-14 14:53:06 -0800293 final int result = super.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700294
Bryce Leef3c6a472017-11-14 14:53:06 -0800295 if (mDisplayContent != null) {
296 updateAnimationBackgroundBounds();
297 }
298
Wale Ogunwale94744212015-09-21 19:01:47 -0700299 mRotation = rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700300 mDensity = density;
Chong Zhangb816b862016-01-25 12:01:12 -0800301
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800302 updateAdjustedBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800303
chaviwe07246a2017-12-12 16:18:29 -0800304 updateSurfaceBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -0800305 return result;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800306 }
307
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700308 /** Bounds of the stack without adjusting for other factors in the system like visibility
309 * of docked stack.
Bryce Leef3c6a472017-11-14 14:53:06 -0800310 * Most callers should be using {@link ConfigurationContainer#getOverrideBounds} as it take into
311 * consideration other system factors. */
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700312 void getRawBounds(Rect out) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800313 out.set(getRawBounds());
314 }
315
316 Rect getRawBounds() {
317 return super.getBounds();
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800318 }
319
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700320 /** Return true if the current bound can get outputted to the rest of the system as-is. */
321 private boolean useCurrentBounds() {
Bryce Leef3c6a472017-11-14 14:53:06 -0800322 if (matchParentBounds()
Wale Ogunwale926aade2017-08-29 11:24:37 -0700323 || !inSplitScreenSecondaryWindowingMode()
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700324 || mDisplayContent == null
chaviw23012112017-12-20 15:29:04 -0800325 || mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700326 return true;
327 }
328 return false;
329 }
330
Bryce Leef3c6a472017-11-14 14:53:06 -0800331 @Override
332 public void getBounds(Rect bounds) {
333 bounds.set(getBounds());
334 }
335
336 @Override
337 public Rect getBounds() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700338 if (useCurrentBounds()) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800339 // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
340 // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
341 // stack is visible since it is already what we want to represent to the rest of the
342 // system.
343 if (!mAdjustedBounds.isEmpty()) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800344 return mAdjustedBounds;
Chong Zhangb816b862016-01-25 12:01:12 -0800345 } else {
Bryce Leef3c6a472017-11-14 14:53:06 -0800346 return super.getBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800347 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700348 }
349
350 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
351 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
352 // system.
Bryce Leef3c6a472017-11-14 14:53:06 -0800353 return mDisplayContent.getBounds();
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700354 }
355
Winson Chung84a38342016-11-08 16:15:10 -0800356 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700357 * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
358 * in onAnimationStart() since that is started on the UiThread.
Winson Chung84a38342016-11-08 16:15:10 -0800359 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700360 void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds, boolean toFullscreen) {
Winson Chung40a5f932017-04-13 16:39:36 -0700361 mBoundsAnimatingRequested = true;
Winson Chung8bca9e42017-04-16 15:59:43 -0700362 mBoundsAnimatingToFullscreen = toFullscreen;
Winson Chung08f81892017-03-02 15:40:51 -0800363 if (destBounds != null) {
364 mBoundsAnimationTarget.set(destBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800365 } else {
366 mBoundsAnimationTarget.setEmpty();
367 }
Winson Chung8bca9e42017-04-16 15:59:43 -0700368 if (sourceHintBounds != null) {
369 mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
370 } else {
371 mBoundsAnimationSourceHintBounds.setEmpty();
372 }
Robert Carr18f622f2017-05-08 11:20:43 -0700373
Bryce Leef3c6a472017-11-14 14:53:06 -0800374 mPreAnimationBounds.set(getRawBounds());
Winson Chung84a38342016-11-08 16:15:10 -0800375 }
376
377 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700378 * @return the final bounds for the bounds animation.
Winson Chung08f81892017-03-02 15:40:51 -0800379 */
Winson Chung40a5f932017-04-13 16:39:36 -0700380 void getFinalAnimationBounds(Rect outBounds) {
381 outBounds.set(mBoundsAnimationTarget);
Winson Chung08f81892017-03-02 15:40:51 -0800382 }
383
384 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700385 * @return the final source bounds for the bounds animation.
Winson Chung84a38342016-11-08 16:15:10 -0800386 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700387 void getFinalAnimationSourceHintBounds(Rect outBounds) {
388 outBounds.set(mBoundsAnimationSourceHintBounds);
Winson Chung40a5f932017-04-13 16:39:36 -0700389 }
390
391 /**
392 * @return the final animation bounds if the task stack is currently being animated, or the
393 * current stack bounds otherwise.
394 */
395 void getAnimationOrCurrentBounds(Rect outBounds) {
396 if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
397 getFinalAnimationBounds(outBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800398 return;
399 }
400 getBounds(outBounds);
401 }
402
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800403 /** Bounds of the stack with other system factors taken into consideration. */
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800404 public void getDimBounds(Rect out) {
405 getBounds(out);
406 }
407
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700408 void updateDisplayInfo(Rect bounds) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800409 if (mDisplayContent == null) {
410 return;
411 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100412
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700413 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
414 mChildren.get(taskNdx).updateDisplayInfo(mDisplayContent);
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800415 }
416 if (bounds != null) {
417 setBounds(bounds);
418 return;
Bryce Leef3c6a472017-11-14 14:53:06 -0800419 } else if (matchParentBounds()) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800420 setBounds(null);
421 return;
422 }
423
Bryce Leef3c6a472017-11-14 14:53:06 -0800424 mTmpRect2.set(getRawBounds());
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800425 final int newRotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700426 final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
427 if (mRotation == newRotation && mDensity == newDensity) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800428 setBounds(mTmpRect2);
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800429 }
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700430
431 // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800432 }
433
Andrii Kulian441e4492016-09-29 15:25:00 -0700434 /** @return true if bounds were updated to some non-empty value. */
435 boolean updateBoundsAfterConfigChange() {
Andrii Kulian0be2cfe2016-05-25 14:27:39 -0700436 if (mDisplayContent == null) {
437 // If the stack is already detached we're not updating anything,
438 // as it's going away soon anyway.
439 return false;
440 }
Winson Chung19953ca2017-04-11 11:19:23 -0700441
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700442 if (inPinnedWindowingMode()) {
Winson Chung40a5f932017-04-13 16:39:36 -0700443 getAnimationOrCurrentBounds(mTmpRect2);
Winson Chung19953ca2017-04-11 11:19:23 -0700444 boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
445 mTmpRect2, mTmpRect3);
446 if (updated) {
447 mBoundsAfterRotation.set(mTmpRect3);
448
449 // Once we've set the bounds based on the rotation of the old bounds in the new
450 // orientation, clear the animation target bounds since they are obsolete, and
451 // cancel any currently running animations
452 mBoundsAnimationTarget.setEmpty();
Winson Chung8bca9e42017-04-16 15:59:43 -0700453 mBoundsAnimationSourceHintBounds.setEmpty();
Winson Chung19953ca2017-04-11 11:19:23 -0700454 mCancelCurrentBoundsAnimation = true;
455 return true;
456 }
457 }
458
Jorim Jaggi737af722015-12-31 10:42:27 +0100459 final int newRotation = getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700460 final int newDensity = getDisplayInfo().logicalDensityDpi;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800461
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700462 if (mRotation == newRotation && mDensity == newDensity) {
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700463 // Nothing to do here as we already update the state in updateDisplayInfo.
Chong Zhang167bbfac2016-03-31 09:44:34 -0700464 return false;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800465 }
466
Bryce Leef3c6a472017-11-14 14:53:06 -0800467 if (matchParentBounds()) {
Chong Zhangccc335c2016-05-13 11:04:38 -0700468 // Update stack bounds again since rotation changed since updateDisplayInfo().
469 setBounds(null);
470 // Return false since we don't need the client to resize.
471 return false;
472 }
473
Bryce Leef3c6a472017-11-14 14:53:06 -0800474 mTmpRect2.set(getRawBounds());
Jorim Jaggi737af722015-12-31 10:42:27 +0100475 mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700476 if (inSplitScreenPrimaryWindowingMode()) {
Matthew Ngcb1b8e42017-10-20 16:29:23 -0700477 repositionPrimarySplitScreenStackAfterRotation(mTmpRect2);
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700478 snapDockedStackAfterRotation(mTmpRect2);
479 final int newDockSide = getDockSide(mTmpRect2);
Winson Chungcd1ff642016-10-26 09:44:43 -0700480
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700481 // Update the dock create mode and clear the dock create bounds, these
482 // might change after a rotation and the original values will be invalid.
483 mService.setDockedStackCreateStateLocked(
484 (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
Matthew Ngbf155872017-10-27 15:24:39 -0700485 ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
486 : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700487 null);
488 mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
Jorim Jaggi737af722015-12-31 10:42:27 +0100489 }
490
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700491 mBoundsAfterRotation.set(mTmpRect2);
Chong Zhang167bbfac2016-03-31 09:44:34 -0700492 return true;
493 }
494
Matthew Ngaa2b6202017-02-10 14:48:21 -0800495 void getBoundsForNewConfiguration(Rect outBounds) {
Chong Zhang167bbfac2016-03-31 09:44:34 -0700496 outBounds.set(mBoundsAfterRotation);
497 mBoundsAfterRotation.setEmpty();
Jorim Jaggi737af722015-12-31 10:42:27 +0100498 }
499
500 /**
Matthew Ngcb1b8e42017-10-20 16:29:23 -0700501 * Some primary split screen sides are not allowed by the policy. This method queries the policy
502 * and moves the primary stack around if needed.
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800503 *
Matthew Ngcb1b8e42017-10-20 16:29:23 -0700504 * @param inOutBounds the bounds of the primary stack to adjust
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800505 */
Matthew Ngcb1b8e42017-10-20 16:29:23 -0700506 private void repositionPrimarySplitScreenStackAfterRotation(Rect inOutBounds) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800507 int dockSide = getDockSide(inOutBounds);
Matthew Ngcb1b8e42017-10-20 16:29:23 -0700508 if (mDisplayContent.getDockedDividerController().canPrimaryStackDockTo(dockSide)) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800509 return;
510 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800511 mDisplayContent.getBounds(mTmpRect);
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800512 dockSide = DockedDividerUtils.invertDockSide(dockSide);
513 switch (dockSide) {
514 case DOCKED_LEFT:
515 int movement = inOutBounds.left;
516 inOutBounds.left -= movement;
517 inOutBounds.right -= movement;
518 break;
519 case DOCKED_RIGHT:
520 movement = mTmpRect.right - inOutBounds.right;
521 inOutBounds.left += movement;
522 inOutBounds.right += movement;
523 break;
524 case DOCKED_TOP:
525 movement = inOutBounds.top;
526 inOutBounds.top -= movement;
527 inOutBounds.bottom -= movement;
528 break;
529 case DOCKED_BOTTOM:
530 movement = mTmpRect.bottom - inOutBounds.bottom;
531 inOutBounds.top += movement;
532 inOutBounds.bottom += movement;
533 break;
534 }
535 }
536
537 /**
Jorim Jaggi737af722015-12-31 10:42:27 +0100538 * Snaps the bounds after rotation to the closest snap target for the docked stack.
539 */
540 private void snapDockedStackAfterRotation(Rect outBounds) {
541
542 // Calculate the current position.
543 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700544 final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
Jorim Jaggi737af722015-12-31 10:42:27 +0100545 final int dockSide = getDockSide(outBounds);
546 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
547 dockSide, dividerSize);
548 final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
549 final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
550
551 // Snap the position to a target.
552 final int rotation = displayInfo.rotation;
Andrii Kulian441e4492016-09-29 15:25:00 -0700553 final int orientation = mDisplayContent.getConfiguration().orientation;
Jorim Jaggi737af722015-12-31 10:42:27 +0100554 mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
555 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Jorim Jaggidf012d52016-01-15 22:40:13 -0800556 mService.mContext.getResources(), displayWidth, displayHeight,
Matthew Nge15352e2016-12-20 15:36:29 -0800557 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
Matthew Ngf59a4132017-10-25 12:03:22 -0700558 getDockSide(), isMinimizedDockAndHomeStackResizable());
Jorim Jaggi737af722015-12-31 10:42:27 +0100559 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
560
561 // Recalculate the bounds based on the position of the target.
562 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
563 outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
564 dividerSize);
565 }
566
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700567 // TODO: Checkout the call points of this method and the ones below to see how they can fit in WC.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800568 void addTask(Task task, int position) {
569 addTask(task, position, task.showForAllUsers(), true /* moveParents */);
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700570 }
571
Craig Mautner00af9fe2013-03-25 09:13:41 -0700572 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800573 * Put a Task in this stack. Used for adding only.
574 * When task is added to top of the stack, the entire branch of the hierarchy (including stack
575 * and display) will be brought to top.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700576 * @param task The task to add.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800577 * @param position Target position to add the task to.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700578 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700579 */
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800580 void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800581 final TaskStack currentStack = task.mStack;
582 // TODO: We pass stack to task's constructor, but we still need to call this method.
583 // This doesn't make sense, mStack will already be set equal to "this" at this point.
584 if (currentStack != null && currentStack.mStackId != mStackId) {
585 throw new IllegalStateException("Trying to add taskId=" + task.mTaskId
586 + " to stackId=" + mStackId
587 + ", but it is already attached to stackId=" + task.mStack.mStackId);
588 }
589
Andrii Kuliand2765632016-12-12 22:26:34 -0800590 // Add child task.
591 task.mStack = this;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800592 addChild(task, null);
Andrii Kuliand2765632016-12-12 22:26:34 -0800593
594 // Move child to a proper position, as some restriction for position might apply.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800595 positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
Andrii Kuliand2765632016-12-12 22:26:34 -0800596 }
597
598 @Override
599 void positionChildAt(int position, Task child, boolean includingParents) {
600 positionChildAt(position, child, includingParents, child.showForAllUsers());
601 }
602
603 /**
604 * Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800605 * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive
Andrii Kuliand2765632016-12-12 22:26:34 -0800606 * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}.
607 */
608 private void positionChildAt(int position, Task child, boolean includingParents,
609 boolean showForAllUsers) {
610 final int targetPosition = findPositionForTask(child, position, showForAllUsers,
611 false /* addingNew */);
612 super.positionChildAt(targetPosition, child, includingParents);
613
614 // Log positioning.
615 if (DEBUG_TASK_MOVEMENT)
616 Slog.d(TAG_WM, "positionTask: task=" + this + " position=" + position);
617
618 final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
619 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700620 }
621
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700622 // TODO: We should really have users as a window container in the hierarchy so that we don't
Andrii Kuliand2765632016-12-12 22:26:34 -0800623 // have to do complicated things like we are doing in this method.
624 private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
625 boolean addingNew) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700626 final boolean canShowTask =
627 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
Andrii Kuliand2765632016-12-12 22:26:34 -0800628
629 final int stackSize = mChildren.size();
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700630 int minPosition = 0;
Andrii Kuliand2765632016-12-12 22:26:34 -0800631 int maxPosition = addingNew ? stackSize : stackSize - 1;
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700632
633 if (canShowTask) {
634 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700635 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700636 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700637 }
Evan Rosky9c448172017-11-02 14:19:27 -0700638
639 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
640 if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
641 return POSITION_BOTTOM;
642 } else if (targetPosition == POSITION_TOP
643 && maxPosition == (addingNew ? stackSize : stackSize - 1)) {
644 return POSITION_TOP;
645 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700646 // Reset position based on minimum/maximum possible positions.
Andrii Kuliand2765632016-12-12 22:26:34 -0800647 return Math.min(Math.max(targetPosition, minPosition), maxPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700648 }
649
650 /** Calculate the minimum possible position for a task that can be shown to the user.
651 * The minimum position will be above all other tasks that can't be shown.
652 * @param minPosition The minimum position the caller is suggesting.
653 * We will start adjusting up from here.
654 * @param size The size of the current task list.
655 */
656 private int computeMinPosition(int minPosition, int size) {
657 while (minPosition < size) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700658 final Task tmpTask = mChildren.get(minPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700659 final boolean canShowTmpTask =
660 tmpTask.showForAllUsers()
661 || mService.isCurrentProfileLocked(tmpTask.mUserId);
662 if (canShowTmpTask) {
663 break;
664 }
665 minPosition++;
666 }
667 return minPosition;
668 }
669
670 /** Calculate the maximum possible position for a task that can't be shown to the user.
671 * The maximum position will be below all other tasks that can be shown.
672 * @param maxPosition The maximum position the caller is suggesting.
673 * We will start adjusting down from here.
674 */
675 private int computeMaxPosition(int maxPosition) {
676 while (maxPosition > 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800677 final Task tmpTask = mChildren.get(maxPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700678 final boolean canShowTmpTask =
679 tmpTask.showForAllUsers()
680 || mService.isCurrentProfileLocked(tmpTask.mUserId);
681 if (!canShowTmpTask) {
682 break;
683 }
684 maxPosition--;
685 }
686 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800687 }
688
Craig Mautner00af9fe2013-03-25 09:13:41 -0700689 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800690 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
691 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700692 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700693 */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700694 @Override
695 void removeChild(Task task) {
696 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700697
698 super.removeChild(task);
Andrii Kuliand2765632016-12-12 22:26:34 -0800699 task.mStack = null;
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700700
Craig Mautnerdf88d732014-01-27 09:21:32 -0800701 if (mDisplayContent != null) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700702 if (mChildren.isEmpty()) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800703 getParent().positionChildAt(POSITION_BOTTOM, this, false /* includingParents */);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800704 }
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700705 mDisplayContent.setLayoutNeeded();
Craig Mautner04a0ea62014-01-13 12:51:26 -0800706 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800707 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
708 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Bryce Lee6d410262017-02-28 15:30:17 -0800709 if (wtoken.getTask() == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800710 wtoken.mIsExiting = false;
711 mExitingAppTokens.remove(appNdx);
712 }
713 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800714 }
715
Wale Ogunwale61911492017-10-11 08:50:50 -0700716 @Override
717 public void onConfigurationChanged(Configuration newParentConfig) {
718 final int prevWindowingMode = getWindowingMode();
Jorim Jaggi1a6d98b2018-01-08 16:23:00 +0100719 super.onConfigurationChanged(newParentConfig);
720
chaviwe07246a2017-12-12 16:18:29 -0800721 // Only need to update surface size here since the super method will handle updating
722 // surface position.
723 updateSurfaceSize(getPendingTransaction());
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800724 final int windowingMode = getWindowingMode();
chaviwe07246a2017-12-12 16:18:29 -0800725
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800726 if (mDisplayContent == null || prevWindowingMode == windowingMode) {
727 return;
Wale Ogunwale61911492017-10-11 08:50:50 -0700728 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800729 mDisplayContent.onStackWindowingModeChanged(this);
730 updateBoundsForWindowModeChange();
Wale Ogunwale61911492017-10-11 08:50:50 -0700731 }
732
chaviwe07246a2017-12-12 16:18:29 -0800733 private void updateSurfaceBounds() {
734 updateSurfaceBounds(getPendingTransaction());
735 scheduleAnimation();
736 }
737
738 void updateSurfaceBounds(SurfaceControl.Transaction transaction) {
739 updateSurfaceSize(transaction);
740 updateSurfacePosition(transaction);
741 }
742
743 private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
744 if (mSurfaceControl == null) {
745 return;
746 }
747
748 final Rect stackBounds = getBounds();
Jorim Jaggi1e8c4c82018-01-09 15:14:15 +0100749 final int width = stackBounds.width();
750 final int height = stackBounds.height();
751 if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
752 return;
753 }
754 transaction.setSize(mSurfaceControl, width, height);
755 mLastSurfaceSize.set(width, height);
chaviwe07246a2017-12-12 16:18:29 -0800756 }
757
Wale Ogunwale61911492017-10-11 08:50:50 -0700758 @Override
Wale Ogunwale02319a62016-09-26 15:21:22 -0700759 void onDisplayChanged(DisplayContent dc) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800760 if (mDisplayContent != null) {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700761 throw new IllegalStateException("onDisplayChanged: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800762 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800763
Wale Ogunwale02319a62016-09-26 15:21:22 -0700764 mDisplayContent = dc;
Robert Carrf59b8dd2017-10-02 18:58:36 -0700765
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800766 updateBoundsForWindowModeChange();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700767 mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer(true)
768 .setName("animation background stackId=" + mStackId)
769 .build();
770
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800771 super.onDisplayChanged(dc);
772 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700773
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800774 private void updateBoundsForWindowModeChange() {
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700775 Rect bounds = null;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800776 final boolean inSplitScreenPrimary = inSplitScreenPrimaryWindowingMode();
777 final TaskStack splitScreenStack =
778 mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
779 if (inSplitScreenPrimary || (splitScreenStack != null
780 && inSplitScreenSecondaryWindowingMode() && !splitScreenStack.fillsParent())) {
Wale Ogunwale3797c222015-10-27 14:21:58 -0700781 // The existence of a docked stack affects the size of other static stack created since
Jorim Jaggi65002e12016-04-21 18:25:49 -0700782 // the docked stack occupies a dedicated region on screen, but only if the dock stack is
783 // not fullscreen. If it's fullscreen, it means that we are in the transition of
784 // dismissing it, so we must not resize this stack.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700785 bounds = new Rect();
Bryce Leef3c6a472017-11-14 14:53:06 -0800786 mDisplayContent.getBounds(mTmpRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700787 mTmpRect2.setEmpty();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800788 if (splitScreenStack != null) {
789 splitScreenStack.getRawBounds(mTmpRect2);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700790 }
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800791 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Matthew Ngbf155872017-10-27 15:24:39 -0700792 == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700793 getStackDockedModeBounds(mTmpRect, bounds, mTmpRect2,
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800794 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700795 } else if (inPinnedWindowingMode()) {
Winson Chung19953ca2017-04-11 11:19:23 -0700796 // Update the bounds based on any changes to the display info
Winson Chung40a5f932017-04-13 16:39:36 -0700797 getAnimationOrCurrentBounds(mTmpRect2);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800798 if (mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
799 mTmpRect2, mTmpRect3)) {
Winson Chung19953ca2017-04-11 11:19:23 -0700800 bounds = new Rect(mTmpRect3);
801 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700802 }
803
804 updateDisplayInfo(bounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700805 }
806
Matthew Ngaa2b6202017-02-10 14:48:21 -0800807 /**
808 * Determines the stack and task bounds of the other stack when in docked mode. The current task
809 * bounds is passed in but depending on the stack, the task and stack must match. Only in
810 * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds
811 * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds
812 * is calculated and is also used for its task bounds.
813 * If any of the out bounds are empty, it represents default bounds
814 *
815 * @param currentTempTaskBounds the current task bounds of the other stack
816 * @param outStackBounds the calculated stack bounds of the other stack
817 * @param outTempTaskBounds the calculated task bounds of the other stack
818 * @param ignoreVisibility ignore visibility in getting the stack bounds
819 */
820 void getStackDockedModeBoundsLocked(Rect currentTempTaskBounds, Rect outStackBounds,
821 Rect outTempTaskBounds, boolean ignoreVisibility) {
822 outTempTaskBounds.setEmpty();
823
824 // When the home stack is resizable, should always have the same stack and task bounds
Wale Ogunwale68278562017-09-23 17:13:55 -0700825 if (isActivityTypeHome()) {
Winson Chungf7fb5e32017-05-23 17:47:05 -0700826 final Task homeTask = findHomeTask();
827 if (homeTask != null && homeTask.isResizeable()) {
Wale Ogunwale649c1602017-04-24 10:15:31 -0700828 // Calculate the home stack bounds when in docked mode and the home stack is
829 // resizeable.
830 getDisplayContent().mDividerControllerLocked
831 .getHomeStackBoundsInDockedMode(outStackBounds);
832 } else {
833 // Home stack isn't resizeable, so don't specify stack bounds.
834 outStackBounds.setEmpty();
835 }
836
Matthew Ngaa2b6202017-02-10 14:48:21 -0800837 outTempTaskBounds.set(outStackBounds);
838 return;
839 }
840
841 // When minimized state, the stack bounds for all non-home and docked stack bounds should
842 // match the passed task bounds
843 if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) {
844 outStackBounds.set(currentTempTaskBounds);
845 return;
Matthew Nge15352e2016-12-20 15:36:29 -0800846 }
847
Wale Ogunwale926aade2017-08-29 11:24:37 -0700848 if (!inSplitScreenWindowingMode() || mDisplayContent == null) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800849 outStackBounds.set(getRawBounds());
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700850 return;
851 }
852
Wale Ogunwale61911492017-10-11 08:50:50 -0700853 final TaskStack dockedStack =
Matthew Ng64e77cf2017-10-31 14:01:31 -0700854 mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700855 if (dockedStack == null) {
856 // Not sure why you are calling this method when there is no docked stack...
857 throw new IllegalStateException(
858 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
859 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700860 if (!ignoreVisibility && !dockedStack.isVisible()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700861 // The docked stack is being dismissed, but we caught before it finished being
862 // dismissed. In that case we want to treat it as if it is not occupying any space and
863 // let others occupy the whole display.
Bryce Leef3c6a472017-11-14 14:53:06 -0800864 mDisplayContent.getBounds(outStackBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700865 return;
866 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700867
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700868 final int dockedSide = dockedStack.getDockSide();
869 if (dockedSide == DOCKED_INVALID) {
870 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800871 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Bryce Leef3c6a472017-11-14 14:53:06 -0800872 outStackBounds.set(getRawBounds());
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700873 return;
874 }
875
Bryce Leef3c6a472017-11-14 14:53:06 -0800876 mDisplayContent.getBounds(mTmpRect);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700877 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800878 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700879 getStackDockedModeBounds(mTmpRect, outStackBounds, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100880 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700881
882 }
883
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700884 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700885 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700886 * @param displayRect The bounds of the display the docked stack is on.
887 * @param outBounds Output bounds that should be used for the stack.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700888 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700889 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
890 * close to the side of the dock.
891 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700892 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800893 private void getStackDockedModeBounds(
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700894 Rect displayRect, Rect outBounds, Rect dockedBounds, int dockDividerWidth,
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700895 boolean dockOnTopOrLeft) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700896 final boolean dockedStack = inSplitScreenPrimaryWindowingMode();
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700897 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700898
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700899 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700900 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800901 if (mService.mDockedStackCreateBounds != null) {
902 outBounds.set(mService.mDockedStackCreateBounds);
903 return;
904 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100905
906 // The initial bounds of the docked stack when it is created about half the screen space
907 // and its bounds can be adjusted after that. The bounds of all other stacks are
908 // adjusted to occupy whatever screen space the docked stack isn't occupying.
909 final DisplayInfo di = mDisplayContent.getDisplayInfo();
910 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
911 mTmpRect2);
912 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100913 di.logicalWidth,
914 di.logicalHeight,
915 dockDividerWidth,
Andrii Kulian441e4492016-09-29 15:25:00 -0700916 mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT,
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100917 mTmpRect2).getMiddleTarget().position;
918
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700919 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700920 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100921 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700922 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100923 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700924 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700925 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700926 if (splitHorizontally) {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700927 outBounds.left = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700928 } else {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700929 outBounds.top = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700930 }
931 }
932 return;
933 }
934
935 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700936 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700937 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700938 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700939 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700940 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700941 }
942 } else {
943 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700944 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700945 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700946 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700947 }
948 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800949 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700950 }
951
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800952 void resetDockedStackToMiddle() {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700953 if (inSplitScreenPrimaryWindowingMode()) {
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800954 throw new IllegalStateException("Not a docked stack=" + this);
955 }
956
957 mService.mDockedStackCreateBounds = null;
958
959 final Rect bounds = new Rect();
Matthew Nge15352e2016-12-20 15:36:29 -0800960 final Rect tempBounds = new Rect();
Matthew Ngaa2b6202017-02-10 14:48:21 -0800961 getStackDockedModeBoundsLocked(null /* currentTempTaskBounds */, bounds, tempBounds,
962 true /*ignoreVisibility*/);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800963 getController().requestResize(bounds);
964 }
965
966 @Override
967 StackWindowController getController() {
968 return (StackWindowController) super.getController();
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800969 }
970
Wale Ogunwale10124582016-09-15 20:25:50 -0700971 @Override
972 void removeIfPossible() {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100973 if (isSelfOrChildAnimating()) {
Wale Ogunwale10124582016-09-15 20:25:50 -0700974 mDeferRemoval = true;
975 return;
976 }
977 removeImmediately();
978 }
979
980 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700981 void onParentSet() {
Robert Carrb1579c82017-09-05 14:54:47 -0700982 super.onParentSet();
983
Wale Ogunwale61911492017-10-11 08:50:50 -0700984 if (getParent() != null || mDisplayContent == null) {
985 return;
986 }
Wale Ogunwale10124582016-09-15 20:25:50 -0700987
Craig Mautnerdf88d732014-01-27 09:21:32 -0800988 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -0700989
990 if (mAnimationBackgroundSurface != null) {
Robert Carrf59b8dd2017-10-02 18:58:36 -0700991 mAnimationBackgroundSurface.destroy();
Wale Ogunwale10124582016-09-15 20:25:50 -0700992 mAnimationBackgroundSurface = null;
993 }
Wale Ogunwale10124582016-09-15 20:25:50 -0700994
Andrii Kulian839def92016-11-02 10:58:58 -0700995 mDisplayContent = null;
996 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700997 }
998
Craig Mautner05d29032013-05-03 13:40:13 -0700999 void resetAnimationBackgroundAnimator() {
1000 mAnimationBackgroundAnimator = null;
Robert Carrf59b8dd2017-10-02 18:58:36 -07001001 hideAnimationSurface();
Craig Mautner05d29032013-05-03 13:40:13 -07001002 }
1003
Craig Mautner05d29032013-05-03 13:40:13 -07001004 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
1005 int animLayer = winAnimator.mAnimLayer;
1006 if (mAnimationBackgroundAnimator == null
1007 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
1008 mAnimationBackgroundAnimator = winAnimator;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -07001009 animLayer = mDisplayContent.getLayerForAnimationBackground(winAnimator);
Robert Carrf59b8dd2017-10-02 18:58:36 -07001010 showAnimationSurface(((color >> 24) & 0xff) / 255f);
Craig Mautner05d29032013-05-03 13:40:13 -07001011 }
1012 }
1013
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001014 // TODO: Should each user have there own stacks?
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001015 @Override
Wale Ogunwale498e8c92015-02-13 09:42:46 -08001016 void switchUser() {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001017 super.switchUser();
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001018 int top = mChildren.size();
Craig Mautnerac6f8432013-07-17 13:24:59 -07001019 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001020 Task task = mChildren.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -07001021 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001022 mChildren.remove(taskNdx);
1023 mChildren.add(task);
Craig Mautnerac6f8432013-07-17 13:24:59 -07001024 --top;
1025 }
1026 }
1027 }
1028
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001029 /**
1030 * Adjusts the stack bounds if the IME is visible.
1031 *
1032 * @param imeWin The IME window.
1033 */
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -07001034 void setAdjustedForIme(WindowState imeWin, boolean forceUpdate) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001035 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -07001036 mImeGoingAway = false;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -07001037 if (!mAdjustedForIme || forceUpdate) {
Jorim Jaggiff71d202016-04-14 13:12:36 -07001038 mAdjustedForIme = true;
1039 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -07001040 mAdjustDividerAmount = 0f;
1041 updateAdjustForIme(0f, 0f, true /* force */);
Jorim Jaggiff71d202016-04-14 13:12:36 -07001042 }
Chong Zhangbaba7832016-03-24 10:21:26 -07001043 }
1044
1045 boolean isAdjustedForIme() {
Chong Zhang5117e272016-05-03 12:47:34 -07001046 return mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -07001047 }
Chong Zhangbaba7832016-03-24 10:21:26 -07001048
1049 boolean isAnimatingForIme() {
1050 return mImeWin != null && mImeWin.isAnimatingLw();
1051 }
1052
1053 /**
1054 * Update the stack's bounds (crop or position) according to the IME window's
1055 * current position. When IME window is animated, the bottom stack is animated
1056 * together to track the IME window's current position, and the top stack is
1057 * cropped as necessary.
1058 *
1059 * @return true if a traversal should be performed after the adjustment.
1060 */
Chong Zhangf347ab52016-04-18 21:02:01 -07001061 boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
1062 if (adjustAmount != mAdjustImeAmount
1063 || adjustDividerAmount != mAdjustDividerAmount || force) {
Jorim Jaggieb88d832016-04-13 20:17:43 -07001064 mAdjustImeAmount = adjustAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -07001065 mAdjustDividerAmount = adjustDividerAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -07001066 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +02001067 return isVisible();
Jorim Jaggieb88d832016-04-13 20:17:43 -07001068 } else {
1069 return false;
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001070 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001071 }
1072
1073 /**
1074 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -07001075 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
1076 * animations; otherwise, set flag and animates the window away together
1077 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001078 */
Chong Zhangbaba7832016-03-24 10:21:26 -07001079 void resetAdjustedForIme(boolean adjustBoundsNow) {
1080 if (adjustBoundsNow) {
1081 mImeWin = null;
Chong Zhangbaba7832016-03-24 10:21:26 -07001082 mImeGoingAway = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -07001083 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -07001084 mAdjustDividerAmount = 0f;
Jorim Jaggif93ac2b2017-10-25 15:20:24 +02001085 if (!mAdjustedForIme) {
1086 return;
1087 }
1088 mAdjustedForIme = false;
Chong Zhangbaba7832016-03-24 10:21:26 -07001089 updateAdjustedBounds();
Wale Ogunwale68278562017-09-23 17:13:55 -07001090 mService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
Chong Zhangbaba7832016-03-24 10:21:26 -07001091 } else {
1092 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001093 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001094 }
1095
1096 /**
1097 * Sets the amount how much we currently minimize our stack.
1098 *
1099 * @param minimizeAmount The amount, between 0 and 1.
1100 * @return Whether the amount has changed and a layout is needed.
1101 */
1102 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
1103 if (minimizeAmount != mMinimizeAmount) {
1104 mMinimizeAmount = minimizeAmount;
1105 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +02001106 return isVisible();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001107 } else {
1108 return false;
1109 }
1110 }
1111
Matthew Nge15352e2016-12-20 15:36:29 -08001112 boolean shouldIgnoreInput() {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001113 return isAdjustedForMinimizedDockedStack() ||
1114 (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable());
Jorim Jaggi409635b2016-04-01 15:32:28 -07001115 }
1116
Jorim Jaggiff71d202016-04-14 13:12:36 -07001117 /**
1118 * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
1119 * to the list of to be drawn windows the service is waiting for.
1120 */
1121 void beginImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001122 for (int j = mChildren.size() - 1; j >= 0; j--) {
1123 final Task task = mChildren.get(j);
Wale Ogunwale44f21802016-09-02 12:49:48 -07001124 if (task.hasContentToDisplay()) {
Jorim Jaggiff71d202016-04-14 13:12:36 -07001125 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001126 task.setWaitingForDrawnIfResizingChanged();
Jorim Jaggiff71d202016-04-14 13:12:36 -07001127 }
1128 }
1129 }
1130
1131 /**
1132 * Resets the resizing state of all windows.
1133 */
1134 void endImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001135 for (int j = mChildren.size() - 1; j >= 0; j--) {
1136 mChildren.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Jorim Jaggiff71d202016-04-14 13:12:36 -07001137 }
1138 }
1139
Chong Zhang198afac2016-04-15 12:03:11 -07001140 int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
1141 return displayContentRect.top + (int)
1142 ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
1143 }
1144
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001145 private boolean adjustForIME(final WindowState imeWin) {
1146 final int dockedSide = getDockSide();
1147 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001148 if (imeWin == null || !dockedTopOrBottom) {
1149 return false;
1150 }
1151
Wale Ogunwaledb506192017-12-08 10:57:32 -08001152 final Rect displayStableRect = mTmpRect;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001153 final Rect contentBounds = mTmpRect2;
1154
1155 // Calculate the content bounds excluding the area occupied by IME
Wale Ogunwaledb506192017-12-08 10:57:32 -08001156 getDisplayContent().getStableRect(displayStableRect);
1157 contentBounds.set(displayStableRect);
Jorim Jaggi5ac2ba22016-04-11 21:14:12 -07001158 int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -07001159
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001160 imeTop += imeWin.getGivenContentInsetsLw().top;
1161 if (contentBounds.bottom > imeTop) {
1162 contentBounds.bottom = imeTop;
1163 }
1164
Wale Ogunwaledb506192017-12-08 10:57:32 -08001165 final int yOffset = displayStableRect.bottom - contentBounds.bottom;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001166
Chong Zhang198afac2016-04-15 12:03:11 -07001167 final int dividerWidth =
1168 getDisplayContent().mDividerControllerLocked.getContentWidth();
1169 final int dividerWidthInactive =
1170 getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
1171
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001172 if (dockedSide == DOCKED_TOP) {
1173 // If this stack is docked on top, we make it smaller so the bottom stack is not
Chong Zhang198afac2016-04-15 12:03:11 -07001174 // occluded by IME. We shift its bottom up by the height of the IME, but
1175 // leaves at least 30% of the top stack visible.
1176 final int minTopStackBottom =
Wale Ogunwaledb506192017-12-08 10:57:32 -08001177 getMinTopStackBottom(displayStableRect, getRawBounds().bottom);
Chong Zhang198afac2016-04-15 12:03:11 -07001178 final int bottom = Math.max(
Bryce Leef3c6a472017-11-14 14:53:06 -08001179 getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
Chong Zhang198afac2016-04-15 12:03:11 -07001180 minTopStackBottom);
Bryce Leef3c6a472017-11-14 14:53:06 -08001181 mTmpAdjustedBounds.set(getRawBounds());
1182 mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount)
1183 * getRawBounds().bottom);
1184 mFullyAdjustedImeBounds.set(getRawBounds());
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001185 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -07001186 // When the stack is on bottom and has no focus, it's only adjusted for divider width.
1187 final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
1188
1189 // When the stack is on bottom and has focus, it needs to be moved up so as to
1190 // not occluded by IME, and at the same time adjusted for divider width.
1191 // We try to move it up by the height of the IME window, but only to the extent
1192 // that leaves at least 30% of the top stack visible.
1193 // 'top' is where the top of bottom stack will move to in this case.
Bryce Leef3c6a472017-11-14 14:53:06 -08001194 final int topBeforeImeAdjust =
1195 getRawBounds().top - dividerWidth + dividerWidthInactive;
Chong Zhangf347ab52016-04-18 21:02:01 -07001196 final int minTopStackBottom =
Wale Ogunwaledb506192017-12-08 10:57:32 -08001197 getMinTopStackBottom(displayStableRect,
Bryce Leef3c6a472017-11-14 14:53:06 -08001198 getRawBounds().top - dividerWidth);
Chong Zhangf347ab52016-04-18 21:02:01 -07001199 final int top = Math.max(
Bryce Leef3c6a472017-11-14 14:53:06 -08001200 getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
Chong Zhang198afac2016-04-15 12:03:11 -07001201
Bryce Leef3c6a472017-11-14 14:53:06 -08001202 mTmpAdjustedBounds.set(getRawBounds());
Chong Zhangf347ab52016-04-18 21:02:01 -07001203 // Account for the adjustment for IME and divider width separately.
1204 // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
1205 // and dividerWidthDelta is due to divider width change only.
Bryce Leef3c6a472017-11-14 14:53:06 -08001206 mTmpAdjustedBounds.top = getRawBounds().top +
Chong Zhangf347ab52016-04-18 21:02:01 -07001207 (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
1208 mAdjustDividerAmount * dividerWidthDelta);
Bryce Leef3c6a472017-11-14 14:53:06 -08001209 mFullyAdjustedImeBounds.set(getRawBounds());
Jorim Jaggieb88d832016-04-13 20:17:43 -07001210 mFullyAdjustedImeBounds.top = top;
Bryce Leef3c6a472017-11-14 14:53:06 -08001211 mFullyAdjustedImeBounds.bottom = top + getRawBounds().height();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001212 }
1213 return true;
1214 }
1215
1216 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
1217 final int dockSide = getDockSide();
1218 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
1219 return false;
1220 }
1221
1222 if (dockSide == DOCKED_TOP) {
Winson Chung303c6b72016-10-24 17:12:49 -07001223 mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001224 int topInset = mTmpRect.top;
Bryce Leef3c6a472017-11-14 14:53:06 -08001225 mTmpAdjustedBounds.set(getRawBounds());
1226 mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount)
1227 * getRawBounds().bottom);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001228 } else if (dockSide == DOCKED_LEFT) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001229 mTmpAdjustedBounds.set(getRawBounds());
1230 final int width = getRawBounds().width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001231 mTmpAdjustedBounds.right =
1232 (int) (minimizeAmount * mDockedStackMinimizeThickness
Bryce Leef3c6a472017-11-14 14:53:06 -08001233 + (1 - minimizeAmount) * getRawBounds().right);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001234 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001235 } else if (dockSide == DOCKED_RIGHT) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001236 mTmpAdjustedBounds.set(getRawBounds());
1237 mTmpAdjustedBounds.left = (int) (minimizeAmount *
1238 (getRawBounds().right - mDockedStackMinimizeThickness)
1239 + (1 - minimizeAmount) * getRawBounds().left);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001240 }
1241 return true;
1242 }
1243
Matthew Nge15352e2016-12-20 15:36:29 -08001244 private boolean isMinimizedDockAndHomeStackResizable() {
1245 return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
1246 && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
1247 }
1248
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001249 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -08001250 * @return the distance in pixels how much the stack gets minimized from it's original size
1251 */
1252 int getMinimizeDistance() {
1253 final int dockSide = getDockSide();
1254 if (dockSide == DOCKED_INVALID) {
1255 return 0;
1256 }
1257
1258 if (dockSide == DOCKED_TOP) {
Winson Chung303c6b72016-10-24 17:12:49 -07001259 mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggif97ed922016-02-18 18:57:07 -08001260 int topInset = mTmpRect.top;
Bryce Leef3c6a472017-11-14 14:53:06 -08001261 return getRawBounds().bottom - topInset;
Jorim Jaggif97ed922016-02-18 18:57:07 -08001262 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001263 return getRawBounds().width() - mDockedStackMinimizeThickness;
Jorim Jaggif97ed922016-02-18 18:57:07 -08001264 } else {
1265 return 0;
1266 }
1267 }
1268
1269 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001270 * Updates the adjustment depending on it's current state.
1271 */
Chong Zhang5117e272016-05-03 12:47:34 -07001272 private void updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001273 boolean adjust = false;
1274 if (mMinimizeAmount != 0f) {
1275 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1276 } else if (mAdjustedForIme) {
1277 adjust = adjustForIME(mImeWin);
1278 }
1279 if (!adjust) {
1280 mTmpAdjustedBounds.setEmpty();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001281 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001282 setAdjustedBounds(mTmpAdjustedBounds);
Chong Zhang198afac2016-04-15 12:03:11 -07001283
Chong Zhangb8da4a72016-05-17 15:07:26 -07001284 final boolean isImeTarget = (mService.getImeFocusStackLocked() == this);
Chong Zhangf347ab52016-04-18 21:02:01 -07001285 if (mAdjustedForIme && adjust && !isImeTarget) {
1286 final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
1287 * IME_ADJUST_DIM_AMOUNT;
Wale Ogunwale68278562017-09-23 17:13:55 -07001288 mService.setResizeDimLayer(true, getWindowingMode(), alpha);
Chong Zhang198afac2016-04-15 12:03:11 -07001289 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001290 }
1291
Chong Zhang5117e272016-05-03 12:47:34 -07001292 void applyAdjustForImeIfNeeded(Task task) {
1293 if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) {
1294 return;
1295 }
1296
Bryce Leef3c6a472017-11-14 14:53:06 -08001297 final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds;
Chong Zhang5117e272016-05-03 12:47:34 -07001298 task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001299 mDisplayContent.setLayoutNeeded();
Chong Zhang5117e272016-05-03 12:47:34 -07001300 }
1301
Bryce Leef3c6a472017-11-14 14:53:06 -08001302
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001303 boolean isAdjustedForMinimizedDockedStack() {
1304 return mMinimizeAmount != 0f;
1305 }
1306
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001307 @CallSuper
1308 @Override
Adrian Roos4921ccf2017-09-28 16:54:06 +02001309 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07001310 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001311 super.writeToProto(proto, WINDOW_CONTAINER, trim);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001312 proto.write(ID, mStackId);
1313 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
Adrian Roos4921ccf2017-09-28 16:54:06 +02001314 mChildren.get(taskNdx).writeToProto(proto, TASKS, trim);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001315 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001316 proto.write(FILLS_PARENT, matchParentBounds());
1317 getRawBounds().writeToProto(proto, BOUNDS);
Robert Carrf59b8dd2017-10-02 18:58:36 -07001318 proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurfaceIsShown);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001319 proto.end(token);
1320 }
1321
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001322 @Override
1323 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001324 pw.println(prefix + "mStackId=" + mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -07001325 pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
Bryce Leef3c6a472017-11-14 14:53:06 -08001326 pw.println(prefix + "mBounds=" + getRawBounds().toShortString());
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001327 if (mMinimizeAmount != 0f) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001328 pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001329 }
1330 if (mAdjustedForIme) {
1331 pw.println(prefix + "mAdjustedForIme=true");
1332 pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
1333 pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
1334 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001335 if (!mAdjustedBounds.isEmpty()) {
1336 pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
1337 }
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001338 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001339 mChildren.get(taskNdx).dump(pw, prefix + " ", dumpAll);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001340 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07001341 if (mAnimationBackgroundSurfaceIsShown) {
1342 pw.println(prefix + "mWindowAnimationBackgroundSurface is shown");
Craig Mautner05d29032013-05-03 13:40:13 -07001343 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001344 if (!mExitingAppTokens.isEmpty()) {
1345 pw.println();
1346 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001347 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001348 WindowToken token = mExitingAppTokens.get(i);
1349 pw.print(" Exiting App #"); pw.print(i);
1350 pw.print(' '); pw.print(token);
1351 pw.println(':');
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001352 token.dump(pw, " ", dumpAll);
Craig Mautnerdc548482014-02-05 13:35:24 -08001353 }
1354 }
Craig Mautner00af9fe2013-03-25 09:13:41 -07001355 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001356
1357 @Override
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001358 boolean fillsParent() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001359 if (useCurrentBounds()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001360 return matchParentBounds();
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001361 }
1362 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
1363 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
1364 // system.
1365 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001366 }
1367
1368 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001369 public String toString() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001370 return "{stackId=" + mStackId + " tasks=" + mChildren + "}";
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001371 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001372
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001373 String getName() {
1374 return toShortString();
1375 }
1376
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001377 public String toShortString() {
1378 return "Stack=" + mStackId;
1379 }
1380
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001381 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001382 * For docked workspace (or workspace that's side-by-side to the docked), provides
1383 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001384 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001385 int getDockSide() {
Bryce Leef3c6a472017-11-14 14:53:06 -08001386 return getDockSide(getRawBounds());
Jorim Jaggi737af722015-12-31 10:42:27 +01001387 }
1388
Wale Ogunwale926aade2017-08-29 11:24:37 -07001389 private int getDockSide(Rect bounds) {
1390 if (!inSplitScreenWindowingMode()) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001391 return DOCKED_INVALID;
1392 }
1393 if (mDisplayContent == null) {
1394 return DOCKED_INVALID;
1395 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001396 mDisplayContent.getBounds(mTmpRect);
Andrii Kulian441e4492016-09-29 15:25:00 -07001397 final int orientation = mDisplayContent.getConfiguration().orientation;
Jorim Jaggi85639432016-05-06 17:27:55 -07001398 return getDockSideUnchecked(bounds, mTmpRect, orientation);
1399 }
1400
1401 static int getDockSideUnchecked(Rect bounds, Rect displayRect, int orientation) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001402 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
1403 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi85639432016-05-06 17:27:55 -07001404 if (bounds.top - displayRect.top <= displayRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001405 return DOCKED_TOP;
1406 } else {
1407 return DOCKED_BOTTOM;
1408 }
1409 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1410 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi85639432016-05-06 17:27:55 -07001411 if (bounds.left - displayRect.left <= displayRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001412 return DOCKED_LEFT;
1413 } else {
1414 return DOCKED_RIGHT;
1415 }
1416 } else {
1417 return DOCKED_INVALID;
1418 }
1419 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001420
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001421 boolean hasTaskForUser(int userId) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001422 for (int i = mChildren.size() - 1; i >= 0; i--) {
1423 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001424 if (task.mUserId == userId) {
1425 return true;
1426 }
1427 }
1428 return false;
1429 }
1430
1431 int taskIdFromPoint(int x, int y) {
1432 getBounds(mTmpRect);
1433 if (!mTmpRect.contains(x, y) || isAdjustedForMinimizedDockedStack()) {
1434 return -1;
1435 }
1436
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001437 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
1438 final Task task = mChildren.get(taskNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001439 final WindowState win = task.getTopVisibleAppMainWindow();
1440 if (win == null) {
1441 continue;
1442 }
1443 // We need to use the task's dim bounds (which is derived from the visible bounds of its
1444 // apps windows) for any touch-related tests. Can't use the task's original bounds
1445 // because it might be adjusted to fit the content frame. For example, the presence of
1446 // the IME adjusting the windows frames when the app window is the IME target.
1447 task.getDimBounds(mTmpRect);
1448 if (mTmpRect.contains(x, y)) {
1449 return task.mTaskId;
1450 }
1451 }
1452
1453 return -1;
1454 }
1455
1456 void findTaskForResizePoint(int x, int y, int delta,
1457 DisplayContent.TaskForResizePointSearchResult results) {
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001458 if (!getWindowConfiguration().canResizeTask()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001459 results.searchDone = true;
1460 return;
1461 }
1462
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001463 for (int i = mChildren.size() - 1; i >= 0; --i) {
1464 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001465 if (task.isFullscreen()) {
1466 results.searchDone = true;
1467 return;
1468 }
1469
1470 // We need to use the task's dim bounds (which is derived from the visible bounds of
1471 // its apps windows) for any touch-related tests. Can't use the task's original
1472 // bounds because it might be adjusted to fit the content frame. One example is when
1473 // the task is put to top-left quadrant, the actual visible area would not start at
1474 // (0,0) after it's adjusted for the status bar.
1475 task.getDimBounds(mTmpRect);
1476 mTmpRect.inset(-delta, -delta);
1477 if (mTmpRect.contains(x, y)) {
1478 mTmpRect.inset(delta, delta);
1479
1480 results.searchDone = true;
1481
1482 if (!mTmpRect.contains(x, y)) {
1483 results.taskForResize = task;
1484 return;
1485 }
1486 // User touched inside the task. No need to look further,
1487 // focus transfer will be handled in ACTION_UP.
1488 return;
1489 }
1490 }
1491 }
1492
1493 void setTouchExcludeRegion(Task focusedTask, int delta, Region touchExcludeRegion,
1494 Rect contentRect, Rect postExclude) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001495 for (int i = mChildren.size() - 1; i >= 0; --i) {
1496 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001497 AppWindowToken token = task.getTopVisibleAppToken();
1498 if (token == null || !token.hasContentToDisplay()) {
1499 continue;
1500 }
1501
1502 /**
1503 * Exclusion region is the region that TapDetector doesn't care about.
1504 * Here we want to remove all non-focused tasks from the exclusion region.
1505 * We also remove the outside touch area for resizing for all freeform
1506 * tasks (including the focused).
1507 *
1508 * We save the focused task region once we find it, and add it back at the end.
Matthew Nge15352e2016-12-20 15:36:29 -08001509 *
1510 * If the task is home stack and it is resizable in the minimized state, we want to
1511 * exclude the docked stack from touch so we need the entire screen area and not just a
1512 * small portion which the home stack currently is resized to.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001513 */
1514
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001515 if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001516 mDisplayContent.getBounds(mTmpRect);
Matthew Nge15352e2016-12-20 15:36:29 -08001517 } else {
1518 task.getDimBounds(mTmpRect);
1519 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001520
1521 if (task == focusedTask) {
1522 // Add the focused task rect back into the exclude region once we are done
1523 // processing stacks.
1524 postExclude.set(mTmpRect);
1525 }
1526
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001527 final boolean isFreeformed = task.inFreeformWindowingMode();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001528 if (task != focusedTask || isFreeformed) {
1529 if (isFreeformed) {
1530 // If the task is freeformed, enlarge the area to account for outside
1531 // touch area for resize.
1532 mTmpRect.inset(-delta, -delta);
1533 // Intersect with display content rect. If we have system decor (status bar/
1534 // navigation bar), we want to exclude that from the tap detection.
1535 // Otherwise, if the app is partially placed under some system button (eg.
1536 // Recents, Home), pressing that button would cause a full series of
1537 // unwanted transfer focus/resume/pause, before we could go home.
1538 mTmpRect.intersect(contentRect);
1539 }
1540 touchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
1541 }
1542 }
1543 }
1544
Winson Chung8bca9e42017-04-16 15:59:43 -07001545 public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
1546 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
1547 synchronized (mService.mWindowMap) {
1548 if (mCancelCurrentBoundsAnimation) {
1549 return false;
1550 }
Winson Chung19953ca2017-04-11 11:19:23 -07001551 }
1552
Robert Carr0d00c2e2016-02-29 17:45:02 -08001553 try {
Winson Chung8bca9e42017-04-16 15:59:43 -07001554 mService.mActivityManager.resizePinnedStack(stackBounds, tempTaskBounds);
Robert Carr0d00c2e2016-02-29 17:45:02 -08001555 } catch (RemoteException e) {
1556 // I don't believe you.
1557 }
1558 return true;
1559 }
1560
Robert Carrecc06b32017-04-18 14:25:10 -07001561 void onAllWindowsDrawn() {
Winson Chunge7ba6862017-05-24 12:13:33 -07001562 if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
Robert Carrecc06b32017-04-18 14:25:10 -07001563 return;
1564 }
1565
1566 mService.mBoundsAnimationController.onAllWindowsDrawn();
1567 }
1568
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001569 @Override // AnimatesBounds
Winson Chungab76bbc2017-08-14 13:33:51 -07001570 public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001571 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001572 synchronized (mService.mWindowMap) {
Winson Chung40a5f932017-04-13 16:39:36 -07001573 mBoundsAnimatingRequested = false;
Robert Carr1ca6a332016-04-11 18:00:43 -07001574 mBoundsAnimating = true;
Winson Chung19953ca2017-04-11 11:19:23 -07001575 mCancelCurrentBoundsAnimation = false;
Robert Carrecc06b32017-04-18 14:25:10 -07001576
1577 // If we are changing UI mode, as in the PiP to fullscreen
1578 // transition, then we need to wait for the window to draw.
1579 if (schedulePipModeChangedCallback) {
1580 forAllWindows((w) -> { w.mWinAnimator.resetDrawState(); },
1581 false /* traverseTopToBottom */);
1582 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001583 }
Winson Chung85d39982017-02-24 15:21:25 -08001584
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001585 if (inPinnedWindowingMode()) {
Winson Chung85d39982017-02-24 15:21:25 -08001586 try {
1587 mService.mActivityManager.notifyPinnedStackAnimationStarted();
1588 } catch (RemoteException e) {
1589 // I don't believe you...
1590 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001591
1592 final PinnedStackWindowController controller =
1593 (PinnedStackWindowController) getController();
1594 if (schedulePipModeChangedCallback && controller != null) {
Winson Chungab76bbc2017-08-14 13:33:51 -07001595 // We need to schedule the PiP mode change before the animation up. It is possible
1596 // in this case for the animation down to not have been completed, so always
1597 // force-schedule and update to the client to ensure that it is notified that it
1598 // is no longer in picture-in-picture mode
1599 controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
Winson Chung8bca9e42017-04-16 15:59:43 -07001600 }
Winson Chung85d39982017-02-24 15:21:25 -08001601 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001602 }
1603
1604 @Override // AnimatesBounds
Winson Chung8bca9e42017-04-16 15:59:43 -07001605 public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
1606 boolean moveToFullscreen) {
1607 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Wale Ogunwalece144522016-02-05 22:51:01 -08001608 synchronized (mService.mWindowMap) {
Robert Carr1ca6a332016-04-11 18:00:43 -07001609 mBoundsAnimating = false;
Robert Carr18f622f2017-05-08 11:20:43 -07001610 for (int i = 0; i < mChildren.size(); i++) {
1611 final Task t = mChildren.get(i);
1612 t.clearPreserveNonFloatingState();
1613 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001614 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001615 }
Winson Chung85d39982017-02-24 15:21:25 -08001616
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001617 if (inPinnedWindowingMode()) {
Robert Carr18f622f2017-05-08 11:20:43 -07001618 // Update to the final bounds if requested. This is done here instead of in the bounds
1619 // animator to allow us to coordinate this after we notify the PiP mode changed
1620
Winson Chung8bca9e42017-04-16 15:59:43 -07001621 final PinnedStackWindowController controller =
1622 (PinnedStackWindowController) getController();
1623 if (schedulePipModeChangedCallback && controller != null) {
1624 // We need to schedule the PiP mode change after the animation down, so use the
1625 // final bounds
1626 controller.updatePictureInPictureModeForPinnedStackAnimation(
Winson Chungab76bbc2017-08-14 13:33:51 -07001627 mBoundsAnimationTarget, false /* forceUpdate */);
Winson Chung8bca9e42017-04-16 15:59:43 -07001628 }
1629
Winson Chung8bca9e42017-04-16 15:59:43 -07001630 if (finalStackSize != null) {
1631 setPinnedStackSize(finalStackSize, null);
1632 }
1633
Wale Ogunwale480dca02016-02-06 13:58:29 -08001634 try {
1635 mService.mActivityManager.notifyPinnedStackAnimationEnded();
Winson Chung8bca9e42017-04-16 15:59:43 -07001636 if (moveToFullscreen) {
1637 mService.mActivityManager.moveTasksToFullscreenStack(mStackId,
1638 true /* onTop */);
1639 }
Wale Ogunwale480dca02016-02-06 13:58:29 -08001640 } catch (RemoteException e) {
1641 // I don't believe you...
1642 }
1643 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001644 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001645
Winson Chung8bca9e42017-04-16 15:59:43 -07001646 /**
1647 * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
1648 * bounds and we have a deferred PiP mode changed callback set with the animation.
1649 */
1650 public boolean deferScheduleMultiWindowModeChanged() {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001651 if (inPinnedWindowingMode()) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001652 return (mBoundsAnimatingRequested || mBoundsAnimating);
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001653 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001654 return false;
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001655 }
1656
Robert Carr8f0a3ad2017-02-15 19:30:28 -08001657 public boolean isForceScaled() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001658 return mBoundsAnimating;
1659 }
1660
Winson Chung40a5f932017-04-13 16:39:36 -07001661 public boolean isAnimatingBounds() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001662 return mBoundsAnimating;
Robert Carr0d00c2e2016-02-29 17:45:02 -08001663 }
Jorim Jaggi6626f542016-08-22 13:08:44 -07001664
Robert Carr18f622f2017-05-08 11:20:43 -07001665 public boolean lastAnimatingBoundsWasToFullscreen() {
1666 return mBoundsAnimatingToFullscreen;
1667 }
1668
Winson Chung40a5f932017-04-13 16:39:36 -07001669 public boolean isAnimatingBoundsToFullscreen() {
Robert Carr18f622f2017-05-08 11:20:43 -07001670 return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
Robert Carr7e4c90e2017-02-15 19:52:38 -08001671 }
1672
Winson Chung8bca9e42017-04-16 15:59:43 -07001673 public boolean pinnedStackResizeDisallowed() {
Winson Chung19953ca2017-04-11 11:19:23 -07001674 if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
1675 return true;
1676 }
1677 return false;
1678 }
1679
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001680 /** Returns true if a removal action is still being deferred. */
1681 boolean checkCompleteDeferredRemoval() {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001682 if (isSelfOrChildAnimating()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001683 return true;
1684 }
Wale Ogunwale10124582016-09-15 20:25:50 -07001685 if (mDeferRemoval) {
1686 removeImmediately();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001687 }
1688
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001689 return super.checkCompleteDeferredRemoval();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001690 }
1691
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001692 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07001693 int getOrientation() {
Wale Ogunwale68278562017-09-23 17:13:55 -07001694 return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
1695 }
1696
1697 private boolean canSpecifyOrientation() {
1698 final int windowingMode = getWindowingMode();
1699 final int activityType = getActivityType();
1700 return windowingMode == WINDOWING_MODE_FULLSCREEN
1701 || activityType == ACTIVITY_TYPE_HOME
1702 || activityType == ACTIVITY_TYPE_RECENTS
1703 || activityType == ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale51362492016-09-08 17:49:17 -07001704 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07001705
1706 Dimmer getDimmer() {
1707 return mDimmer;
1708 }
1709
1710 @Override
1711 void prepareSurfaces() {
1712 mDimmer.resetDimStates();
1713 super.prepareSurfaces();
1714 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08001715
1716 // Bounds need to be relative, as the dim layer is a child.
1717 mTmpDimBoundsRect.offsetTo(0, 0);
Robert Carrf59b8dd2017-10-02 18:58:36 -07001718 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
1719 scheduleAnimation();
1720 }
1721 }
1722
1723 public DisplayInfo getDisplayInfo() {
1724 return mDisplayContent.getDisplayInfo();
1725 }
1726
1727 void dim(float alpha) {
1728 mDimmer.dimAbove(getPendingTransaction(), alpha);
1729 scheduleAnimation();
1730 }
1731
1732 void stopDimming() {
1733 mDimmer.stopDim(getPendingTransaction());
1734 scheduleAnimation();
1735 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001736}