blob: 343a972801ddda879ec9790a058b6a40b2843ff4 [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
Wale Ogunwale65ebd952018-04-25 15:41:44 -070019import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT;
20import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
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;
Yunfan Chen279f5582018-12-12 15:24:50 -080024import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Robert Carr32bcb102018-01-29 15:03:23 -080025import static android.app.WindowConfiguration.PINNED_WINDOWING_MODE_ELEVATION_IN_DIP;
Wale Ogunwale68278562017-09-23 17:13:55 -070026import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Evan Roskye747c3e2018-10-30 20:06:41 -070027import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Wale Ogunwale51362492016-09-08 17:49:17 -070028import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070029import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Winson Chung303c6b72016-10-24 17:12:49 -070030import static android.view.Display.DEFAULT_DISPLAY;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070031import static android.view.WindowManager.DOCKED_BOTTOM;
32import static android.view.WindowManager.DOCKED_INVALID;
33import static android.view.WindowManager.DOCKED_LEFT;
34import static android.view.WindowManager.DOCKED_RIGHT;
35import static android.view.WindowManager.DOCKED_TOP;
Garfield Tandec96db2018-10-30 11:28:49 -070036
Tracy Zhou9c675d42019-04-08 00:32:40 -070037import static com.android.server.wm.BoundsAnimationController.FADE_IN;
Yunfan Chen279f5582018-12-12 15:24:50 -080038import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
39import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
40import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_START;
41import static com.android.server.wm.BoundsAnimationController.SchedulePipModeChangedState;
Jorim Jaggiff71d202016-04-14 13:12:36 -070042import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070043import static com.android.server.wm.StackProto.ADJUSTED_BOUNDS;
44import static com.android.server.wm.StackProto.ADJUSTED_FOR_IME;
45import static com.android.server.wm.StackProto.ADJUST_DIVIDER_AMOUNT;
46import static com.android.server.wm.StackProto.ADJUST_IME_AMOUNT;
Winson Chung82267ce2018-04-06 16:38:26 -070047import static com.android.server.wm.StackProto.ANIMATING_BOUNDS;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070048import static com.android.server.wm.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
49import static com.android.server.wm.StackProto.BOUNDS;
50import static com.android.server.wm.StackProto.DEFER_REMOVAL;
51import static com.android.server.wm.StackProto.FILLS_PARENT;
52import static com.android.server.wm.StackProto.ID;
53import static com.android.server.wm.StackProto.MINIMIZE_AMOUNT;
54import static com.android.server.wm.StackProto.TASKS;
55import static com.android.server.wm.StackProto.WINDOW_CONTAINER;
Yunfan Chen279f5582018-12-12 15:24:50 -080056import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
Winson Chung6a38fca2018-03-28 17:57:09 -070057import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
58import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070059
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070060import android.annotation.CallSuper;
Yunfan Chen279f5582018-12-12 15:24:50 -080061import android.app.RemoteAction;
Wale Ogunwale60454db2015-01-23 16:05:07 -080062import android.content.res.Configuration;
chaviw3e751af2018-01-11 11:22:39 -080063import android.graphics.Point;
Craig Mautner05d29032013-05-03 13:40:13 -070064import android.graphics.Rect;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -070065import android.graphics.Region;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080066import android.os.RemoteException;
Robert Carr32bcb102018-01-29 15:03:23 -080067import android.util.DisplayMetrics;
Craig Mautner2c2549c2013-11-12 08:31:15 -080068import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070069import android.util.Slog;
Steven Timotiusaf03df62017-07-18 16:56:43 -070070import android.util.proto.ProtoOutputStream;
Evan Rosky39b6f232018-10-30 18:35:41 -070071import android.view.DisplayCutout;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070072import android.view.DisplayInfo;
Robert Carrf59b8dd2017-10-02 18:58:36 -070073import android.view.SurfaceControl;
Garfield Tandec96db2018-10-30 11:28:49 -070074
Riddle Hsu6619acb2019-02-20 19:12:57 +080075import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggi737af722015-12-31 10:42:27 +010076import com.android.internal.policy.DividerSnapAlgorithm;
77import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
78import com.android.internal.policy.DockedDividerUtils;
Craig Mautner2c2549c2013-11-12 08:31:15 -080079import com.android.server.EventLogTags;
Garfield Tandec96db2018-10-30 11:28:49 -070080
Craig Mautner00af9fe2013-03-25 09:13:41 -070081import java.io.PrintWriter;
Yunfan Chen279f5582018-12-12 15:24:50 -080082import java.util.List;
Craig Mautnerc00204b2013-03-05 15:02:14 -080083
Robert Carrf59b8dd2017-10-02 18:58:36 -070084public class TaskStack extends WindowContainer<Task> implements
Yunfan Chen279f5582018-12-12 15:24:50 -080085 BoundsAnimationTarget, ConfigurationContainerListener {
Chong Zhang198afac2016-04-15 12:03:11 -070086 /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
87 * restrict IME adjustment so that a min portion of top stack remains visible.*/
88 private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
89
90 /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
91 private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070092
Craig Mautner00af9fe2013-03-25 09:13:41 -070093 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080094 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070095
Craig Mautnerb660b9d2014-02-13 10:59:16 -080096 /** For comparison with DisplayContent bounds. */
97 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070098 private Rect mTmpRect2 = new Rect();
Winson Chung19953ca2017-04-11 11:19:23 -070099 private Rect mTmpRect3 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800100
Yunfan Chen279f5582018-12-12 15:24:50 -0800101 /** For Pinned stack controlling. */
102 private Rect mTmpFromBounds = new Rect();
103 private Rect mTmpToBounds = new Rect();
104
Chong Zhangb816b862016-01-25 12:01:12 -0800105 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
106 private final Rect mAdjustedBounds = new Rect();
107
Jorim Jaggieb88d832016-04-13 20:17:43 -0700108 /**
109 * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
110 * represent the state when the animation has ended.
111 */
112 private final Rect mFullyAdjustedImeBounds = new Rect();
113
Robert Carrf59b8dd2017-10-02 18:58:36 -0700114 private SurfaceControl mAnimationBackgroundSurface;
115 private boolean mAnimationBackgroundSurfaceIsShown = false;
Craig Mautner05d29032013-05-03 13:40:13 -0700116
117 /** The particular window with an Animation with non-zero background color. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700118 private WindowStateAnimator mAnimationBackgroundAnimator;
Craig Mautner05d29032013-05-03 13:40:13 -0700119
Craig Mautnerdc548482014-02-05 13:35:24 -0800120 /** Application tokens that are exiting, but still on screen for animations. */
121 final AppTokenList mExitingAppTokens = new AppTokenList();
Wale Ogunwale48458e12017-06-06 10:07:58 -0700122 final AppTokenList mTmpAppTokens = new AppTokenList();
Craig Mautnerdc548482014-02-05 13:35:24 -0800123
Craig Mautner95da1082014-02-24 17:54:35 -0800124 /** Detach this stack from its display when animation completes. */
Wale Ogunwalef6192862016-09-10 13:42:30 -0700125 // TODO: maybe tie this to WindowContainer#removeChild some how...
Wale Ogunwale10124582016-09-15 20:25:50 -0700126 boolean mDeferRemoval;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800127
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800128 private final Rect mTmpAdjustedBounds = new Rect();
129 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700130 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800131 private WindowState mImeWin;
132 private float mMinimizeAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700133 private float mAdjustImeAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700134 private float mAdjustDividerAmount;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800135 private final int mDockedStackMinimizeThickness;
136
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700137 // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
138 // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
139 // would otherwise apply while resizing, while resizing in the bounds animating mode.
Robert Carr1ca6a332016-04-11 18:00:43 -0700140 private boolean mBoundsAnimating = false;
Winson Chung40a5f932017-04-13 16:39:36 -0700141 // Set when an animation has been requested but has not yet started from the UI thread. This is
142 // cleared when the animation actually starts.
143 private boolean mBoundsAnimatingRequested = false;
Robert Carr7e4c90e2017-02-15 19:52:38 -0800144 private boolean mBoundsAnimatingToFullscreen = false;
Winson Chung19953ca2017-04-11 11:19:23 -0700145 private boolean mCancelCurrentBoundsAnimation = false;
Winson Chung84a38342016-11-08 16:15:10 -0800146 private Rect mBoundsAnimationTarget = new Rect();
Winson Chung8bca9e42017-04-16 15:59:43 -0700147 private Rect mBoundsAnimationSourceHintBounds = new Rect();
Tracy Zhou9c675d42019-04-08 00:32:40 -0700148 private @BoundsAnimationController.AnimationType int mAnimationType;
Robert Carr0d00c2e2016-02-29 17:45:02 -0800149
Robert Carr18f622f2017-05-08 11:20:43 -0700150 Rect mPreAnimationBounds = new Rect();
151
Robert Carrf59b8dd2017-10-02 18:58:36 -0700152 private Dimmer mDimmer = new Dimmer(this);
153
Yunfan Chen279f5582018-12-12 15:24:50 -0800154 // TODO: remove after unification.
155 ActivityStack mActivityStack;
156
Robert Carrf59b8dd2017-10-02 18:58:36 -0700157 /**
158 * For {@link #prepareSurfaces}.
159 */
160 final Rect mTmpDimBoundsRect = new Rect();
chaviw3e751af2018-01-11 11:22:39 -0800161 private final Point mLastSurfaceSize = new Point();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700162
Jorim Jaggi6de61012018-03-19 14:53:23 +0100163 private final AnimatingAppWindowTokenRegistry mAnimatingAppWindowTokenRegistry =
164 new AnimatingAppWindowTokenRegistry();
165
Yunfan Chen279f5582018-12-12 15:24:50 -0800166 TaskStack(WindowManagerService service, int stackId, ActivityStack activityStack) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100167 super(service);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800168 mStackId = stackId;
Yunfan Chen279f5582018-12-12 15:24:50 -0800169 mActivityStack = activityStack;
170 activityStack.registerConfigurationChangeListener(this);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800171 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
172 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700173 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800174 }
175
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700176 Task findHomeTask() {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700177 if (!isActivityTypeHome() || mChildren.isEmpty()) {
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700178 return null;
179 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700180 return mChildren.get(mChildren.size() - 1);
Wale Ogunwale15ead902016-09-02 14:30:11 -0700181 }
182
Jorim Jaggi0429f352015-12-22 16:29:16 +0100183 void prepareFreezingTaskBounds() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700184 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
185 final Task task = mChildren.get(taskNdx);
Jorim Jaggi0429f352015-12-22 16:29:16 +0100186 task.prepareFreezingBounds();
187 }
188 }
189
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800190 /**
191 * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
192 * the normal task bounds.
193 *
194 * @param bounds The adjusted bounds.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800195 */
Jorim Jaggieb88d832016-04-13 20:17:43 -0700196 private void setAdjustedBounds(Rect bounds) {
197 if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
198 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800199 }
200
201 mAdjustedBounds.set(bounds);
202 final boolean adjusted = !mAdjustedBounds.isEmpty();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700203 Rect insetBounds = null;
Matthew Nge15352e2016-12-20 15:36:29 -0800204 if (adjusted && isAdjustedForMinimizedDockedStack()) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800205 insetBounds = getRawBounds();
Chong Zhang5117e272016-05-03 12:47:34 -0700206 } else if (adjusted && mAdjustedForIme) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700207 if (mImeGoingAway) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800208 insetBounds = getRawBounds();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700209 } else {
210 insetBounds = mFullyAdjustedImeBounds;
211 }
212 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800213 alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : getRawBounds(), insetBounds);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700214 mDisplayContent.setLayoutNeeded();
chaviwe07246a2017-12-12 16:18:29 -0800215
216 updateSurfaceBounds();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800217 }
218
219 private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800220 if (matchParentBounds()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800221 return;
222 }
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700223
224 final boolean alignBottom = mAdjustedForIme && getDockSide() == DOCKED_TOP;
225
Chong Zhangb816b862016-01-25 12:01:12 -0800226 // Update bounds of containing tasks.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700227 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
228 final Task task = mChildren.get(taskNdx);
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700229 task.alignToAdjustedBounds(adjustedBounds, tempInsetBounds, alignBottom);
Chong Zhangb816b862016-01-25 12:01:12 -0800230 }
231 }
232
Bryce Leef3c6a472017-11-14 14:53:06 -0800233 private void updateAnimationBackgroundBounds() {
Robert Carrf59b8dd2017-10-02 18:58:36 -0700234 if (mAnimationBackgroundSurface == null) {
235 return;
236 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800237 getRawBounds(mTmpRect);
chaviwe07246a2017-12-12 16:18:29 -0800238 final Rect stackBounds = getBounds();
239 getPendingTransaction()
Vishnu Naird454442d2018-11-13 13:51:01 -0800240 .setWindowCrop(mAnimationBackgroundSurface, mTmpRect.width(), mTmpRect.height())
chaviwe07246a2017-12-12 16:18:29 -0800241 .setPosition(mAnimationBackgroundSurface, mTmpRect.left - stackBounds.left,
242 mTmpRect.top - stackBounds.top);
Robert Carrf59b8dd2017-10-02 18:58:36 -0700243 scheduleAnimation();
244 }
245
246 private void hideAnimationSurface() {
247 if (mAnimationBackgroundSurface == null) {
248 return;
249 }
250 getPendingTransaction().hide(mAnimationBackgroundSurface);
251 mAnimationBackgroundSurfaceIsShown = false;
252 scheduleAnimation();
253 }
254
255 private void showAnimationSurface(float alpha) {
256 if (mAnimationBackgroundSurface == null) {
257 return;
258 }
259 getPendingTransaction().setLayer(mAnimationBackgroundSurface, Integer.MIN_VALUE)
260 .setAlpha(mAnimationBackgroundSurface, alpha)
261 .show(mAnimationBackgroundSurface);
262 mAnimationBackgroundSurfaceIsShown = true;
263 scheduleAnimation();
264 }
265
Bryce Leef3c6a472017-11-14 14:53:06 -0800266 @Override
267 public int setBounds(Rect bounds) {
Evan Roskydfe3da72018-10-26 17:21:06 -0700268 return setBounds(getRequestedOverrideBounds(), bounds);
Bryce Leef3c6a472017-11-14 14:53:06 -0800269 }
270
271 private int setBounds(Rect existing, Rect bounds) {
Evan Roskyc5abbd82018-10-05 16:02:19 -0700272 if (equivalentBounds(existing, bounds)) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800273 return BOUNDS_CHANGE_NONE;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800274 }
275
Bryce Leef3c6a472017-11-14 14:53:06 -0800276 final int result = super.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700277
Evan Roskyc5abbd82018-10-05 16:02:19 -0700278 if (getParent() != null) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800279 updateAnimationBackgroundBounds();
280 }
281
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800282 updateAdjustedBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800283
chaviwe07246a2017-12-12 16:18:29 -0800284 updateSurfaceBounds();
Bryce Leef3c6a472017-11-14 14:53:06 -0800285 return result;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800286 }
287
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700288 /** Bounds of the stack without adjusting for other factors in the system like visibility
289 * of docked stack.
Evan Roskydfe3da72018-10-26 17:21:06 -0700290 * Most callers should be using {@link ConfigurationContainer#getRequestedOverrideBounds} a
291 * it takes into consideration other system factors. */
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700292 void getRawBounds(Rect out) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800293 out.set(getRawBounds());
294 }
295
296 Rect getRawBounds() {
297 return super.getBounds();
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800298 }
299
Bryce Leef3c6a472017-11-14 14:53:06 -0800300 @Override
301 public void getBounds(Rect bounds) {
302 bounds.set(getBounds());
303 }
304
305 @Override
306 public Rect getBounds() {
Evan Rosky4fb1e912019-03-06 13:54:43 -0800307 // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
308 // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
309 // stack is visible since it is already what we want to represent to the rest of the
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700310 // system.
Evan Rosky4fb1e912019-03-06 13:54:43 -0800311 if (!mAdjustedBounds.isEmpty()) {
312 return mAdjustedBounds;
313 } else {
314 return super.getBounds();
315 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700316 }
317
Winson Chung84a38342016-11-08 16:15:10 -0800318 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700319 * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
320 * in onAnimationStart() since that is started on the UiThread.
Winson Chung84a38342016-11-08 16:15:10 -0800321 */
chaviw01f1aa42019-05-14 10:08:12 -0700322 private void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds,
323 boolean toFullscreen) {
Winson Chung40a5f932017-04-13 16:39:36 -0700324 mBoundsAnimatingRequested = true;
Winson Chung8bca9e42017-04-16 15:59:43 -0700325 mBoundsAnimatingToFullscreen = toFullscreen;
Winson Chung08f81892017-03-02 15:40:51 -0800326 if (destBounds != null) {
327 mBoundsAnimationTarget.set(destBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800328 } else {
329 mBoundsAnimationTarget.setEmpty();
330 }
Winson Chung8bca9e42017-04-16 15:59:43 -0700331 if (sourceHintBounds != null) {
332 mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
chaviw01f1aa42019-05-14 10:08:12 -0700333 } else if (!mBoundsAnimating) {
334 // If the bounds are already animating, we don't want to reset the source hint. This is
335 // because the source hint is sent when starting the animation from the client that
336 // requested to enter pip. Other requests can adjust the pip bounds during an animation,
337 // but could accidentally reset the source hint bounds.
Winson Chung8bca9e42017-04-16 15:59:43 -0700338 mBoundsAnimationSourceHintBounds.setEmpty();
339 }
Robert Carr18f622f2017-05-08 11:20:43 -0700340
Bryce Leef3c6a472017-11-14 14:53:06 -0800341 mPreAnimationBounds.set(getRawBounds());
Winson Chung84a38342016-11-08 16:15:10 -0800342 }
343
344 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700345 * @return the final bounds for the bounds animation.
Winson Chung08f81892017-03-02 15:40:51 -0800346 */
Winson Chung40a5f932017-04-13 16:39:36 -0700347 void getFinalAnimationBounds(Rect outBounds) {
348 outBounds.set(mBoundsAnimationTarget);
Winson Chung08f81892017-03-02 15:40:51 -0800349 }
350
351 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700352 * @return the final source bounds for the bounds animation.
Winson Chung84a38342016-11-08 16:15:10 -0800353 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700354 void getFinalAnimationSourceHintBounds(Rect outBounds) {
355 outBounds.set(mBoundsAnimationSourceHintBounds);
Winson Chung40a5f932017-04-13 16:39:36 -0700356 }
357
358 /**
359 * @return the final animation bounds if the task stack is currently being animated, or the
360 * current stack bounds otherwise.
361 */
362 void getAnimationOrCurrentBounds(Rect outBounds) {
363 if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
364 getFinalAnimationBounds(outBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800365 return;
366 }
367 getBounds(outBounds);
368 }
369
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800370 /** Bounds of the stack with other system factors taken into consideration. */
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800371 public void getDimBounds(Rect out) {
372 getBounds(out);
373 }
374
Evan Roskye747c3e2018-10-30 20:06:41 -0700375 /**
Evan Roskyc5abbd82018-10-05 16:02:19 -0700376 * Updates the passed-in {@code inOutBounds} based on the current state of the
377 * pinned controller. This gets run *after* the override configuration is updated, so it's
378 * safe to rely on the controller's state in here (though eventually this dependence should
379 * be removed).
Evan Roskye747c3e2018-10-30 20:06:41 -0700380 *
381 * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700382 * update pinned controller state.
Evan Roskye747c3e2018-10-30 20:06:41 -0700383 *
Evan Roskye747c3e2018-10-30 20:06:41 -0700384 * @param inOutBounds the bounds to update (both input and output).
Evan Roskyc5abbd82018-10-05 16:02:19 -0700385 * @return true if bounds were updated to some non-empty value.
386 */
387 boolean calculatePinnedBoundsForConfigChange(Rect inOutBounds) {
wilsonshih4dd07122019-04-03 15:55:02 +0800388 boolean animating = false;
Evan Roskyc5abbd82018-10-05 16:02:19 -0700389 if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
wilsonshih4dd07122019-04-03 15:55:02 +0800390 animating = true;
Evan Roskyc5abbd82018-10-05 16:02:19 -0700391 getFinalAnimationBounds(mTmpRect2);
392 } else {
393 mTmpRect2.set(inOutBounds);
Winson Chung19953ca2017-04-11 11:19:23 -0700394 }
Evan Roskyc5abbd82018-10-05 16:02:19 -0700395 boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
396 mTmpRect2, mTmpRect3);
397 if (updated) {
398 inOutBounds.set(mTmpRect3);
Winson Chung19953ca2017-04-11 11:19:23 -0700399
wilsonshih4dd07122019-04-03 15:55:02 +0800400 // The final boundary is updated while there is an existing boundary animation. Let's
401 // cancel this animation to prevent the obsolete animation overwritten updated bounds.
402 if (animating && !inOutBounds.equals(mBoundsAnimationTarget)) {
403 final DisplayContent displayContent = getDisplayContent();
404 displayContent.mBoundsAnimationController.getHandler().post(() ->
405 displayContent.mBoundsAnimationController.cancel(this));
406 }
Evan Roskyc5abbd82018-10-05 16:02:19 -0700407 // Once we've set the bounds based on the rotation of the old bounds in the new
408 // orientation, clear the animation target bounds since they are obsolete, and
409 // cancel any currently running animations
410 mBoundsAnimationTarget.setEmpty();
411 mBoundsAnimationSourceHintBounds.setEmpty();
412 mCancelCurrentBoundsAnimation = true;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800413 }
Evan Roskyc5abbd82018-10-05 16:02:19 -0700414 return updated;
415 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800416
Evan Roskyc5abbd82018-10-05 16:02:19 -0700417 /**
418 * Updates the passed-in {@code inOutBounds} based on the current state of the
419 * docked controller. This gets run *after* the override configuration is updated, so it's
420 * safe to rely on the controller's state in here (though eventually this dependence should
421 * be removed).
422 *
423 * This does NOT modify this TaskStack's configuration. However, it does, for the time-being,
424 * update docked controller state.
425 *
426 * @param parentConfig the parent configuration for reference.
427 * @param inOutBounds the bounds to update (both input and output).
428 */
429 void calculateDockedBoundsForConfigChange(Configuration parentConfig, Rect inOutBounds) {
Evan Roskydfe3da72018-10-26 17:21:06 -0700430 final boolean primary =
431 getRequestedOverrideWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
Evan Roskyc5abbd82018-10-05 16:02:19 -0700432 repositionSplitScreenStackAfterRotation(parentConfig, primary, inOutBounds);
433 final DisplayCutout cutout = mDisplayContent.getDisplayInfo().displayCutout;
434 snapDockedStackAfterRotation(parentConfig, cutout, inOutBounds);
435 if (primary) {
436 final int newDockSide = getDockSide(parentConfig, inOutBounds);
437 // Update the dock create mode and clear the dock create bounds, these
438 // might change after a rotation and the original values will be invalid.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800439 mWmService.setDockedStackCreateStateLocked(
Evan Roskyc5abbd82018-10-05 16:02:19 -0700440 (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
441 ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
442 : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT,
443 null);
444 mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
Chong Zhangccc335c2016-05-13 11:04:38 -0700445 }
Chong Zhang167bbfac2016-03-31 09:44:34 -0700446 }
447
Jorim Jaggi737af722015-12-31 10:42:27 +0100448 /**
Matthew Ngcb1b8e42017-10-20 16:29:23 -0700449 * Some primary split screen sides are not allowed by the policy. This method queries the policy
450 * and moves the primary stack around if needed.
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800451 *
Evan Rosky39b6f232018-10-30 18:35:41 -0700452 * @param parentConfig the configuration of the stack's parent.
453 * @param primary true if adjusting the primary docked stack, false for secondary.
454 * @param inOutBounds the bounds of the stack to adjust.
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800455 */
Evan Rosky39b6f232018-10-30 18:35:41 -0700456 void repositionSplitScreenStackAfterRotation(Configuration parentConfig, boolean primary,
457 Rect inOutBounds) {
458 final int dockSide = getDockSide(mDisplayContent, parentConfig, inOutBounds);
459 final int otherDockSide = DockedDividerUtils.invertDockSide(dockSide);
460 final int primaryDockSide = primary ? dockSide : otherDockSide;
461 if (mDisplayContent.getDockedDividerController()
462 .canPrimaryStackDockTo(primaryDockSide,
463 parentConfig.windowConfiguration.getBounds(),
Evan Roskye747c3e2018-10-30 20:06:41 -0700464 parentConfig.windowConfiguration.getRotation())) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800465 return;
466 }
Evan Rosky39b6f232018-10-30 18:35:41 -0700467 final Rect parentBounds = parentConfig.windowConfiguration.getBounds();
468 switch (otherDockSide) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800469 case DOCKED_LEFT:
470 int movement = inOutBounds.left;
471 inOutBounds.left -= movement;
472 inOutBounds.right -= movement;
473 break;
474 case DOCKED_RIGHT:
Evan Rosky39b6f232018-10-30 18:35:41 -0700475 movement = parentBounds.right - inOutBounds.right;
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800476 inOutBounds.left += movement;
477 inOutBounds.right += movement;
478 break;
479 case DOCKED_TOP:
480 movement = inOutBounds.top;
481 inOutBounds.top -= movement;
482 inOutBounds.bottom -= movement;
483 break;
484 case DOCKED_BOTTOM:
Evan Rosky39b6f232018-10-30 18:35:41 -0700485 movement = parentBounds.bottom - inOutBounds.bottom;
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800486 inOutBounds.top += movement;
487 inOutBounds.bottom += movement;
488 break;
489 }
490 }
491
492 /**
Jorim Jaggi737af722015-12-31 10:42:27 +0100493 * Snaps the bounds after rotation to the closest snap target for the docked stack.
494 */
Evan Rosky39b6f232018-10-30 18:35:41 -0700495 void snapDockedStackAfterRotation(Configuration parentConfig, DisplayCutout displayCutout,
496 Rect outBounds) {
Jorim Jaggi737af722015-12-31 10:42:27 +0100497
498 // Calculate the current position.
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700499 final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
Evan Rosky39b6f232018-10-30 18:35:41 -0700500 final int dockSide = getDockSide(parentConfig, outBounds);
Jorim Jaggi737af722015-12-31 10:42:27 +0100501 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
502 dockSide, dividerSize);
Evan Rosky39b6f232018-10-30 18:35:41 -0700503 final int displayWidth = parentConfig.windowConfiguration.getBounds().width();
504 final int displayHeight = parentConfig.windowConfiguration.getBounds().height();
Jorim Jaggi737af722015-12-31 10:42:27 +0100505
506 // Snap the position to a target.
Evan Roskye747c3e2018-10-30 20:06:41 -0700507 final int rotation = parentConfig.windowConfiguration.getRotation();
Evan Rosky39b6f232018-10-30 18:35:41 -0700508 final int orientation = parentConfig.orientation;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800509 mDisplayContent.getDisplayPolicy().getStableInsetsLw(rotation, displayWidth, displayHeight,
Evan Rosky39b6f232018-10-30 18:35:41 -0700510 displayCutout, outBounds);
Jorim Jaggi737af722015-12-31 10:42:27 +0100511 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800512 mWmService.mContext.getResources(), displayWidth, displayHeight,
Matthew Nge15352e2016-12-20 15:36:29 -0800513 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
Matthew Ngf59a4132017-10-25 12:03:22 -0700514 getDockSide(), isMinimizedDockAndHomeStackResizable());
Jorim Jaggi737af722015-12-31 10:42:27 +0100515 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
516
517 // Recalculate the bounds based on the position of the target.
518 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
Evan Rosky39b6f232018-10-30 18:35:41 -0700519 outBounds, displayWidth, displayHeight,
Jorim Jaggi737af722015-12-31 10:42:27 +0100520 dividerSize);
521 }
522
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700523 // 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 -0800524 void addTask(Task task, int position) {
525 addTask(task, position, task.showForAllUsers(), true /* moveParents */);
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700526 }
527
Craig Mautner00af9fe2013-03-25 09:13:41 -0700528 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800529 * Put a Task in this stack. Used for adding only.
530 * When task is added to top of the stack, the entire branch of the hierarchy (including stack
531 * and display) will be brought to top.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700532 * @param task The task to add.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800533 * @param position Target position to add the task to.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700534 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700535 */
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800536 void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800537 final TaskStack currentStack = task.mStack;
538 // TODO: We pass stack to task's constructor, but we still need to call this method.
539 // This doesn't make sense, mStack will already be set equal to "this" at this point.
540 if (currentStack != null && currentStack.mStackId != mStackId) {
541 throw new IllegalStateException("Trying to add taskId=" + task.mTaskId
542 + " to stackId=" + mStackId
543 + ", but it is already attached to stackId=" + task.mStack.mStackId);
544 }
545
Andrii Kuliand2765632016-12-12 22:26:34 -0800546 // Add child task.
547 task.mStack = this;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800548 addChild(task, null);
Andrii Kuliand2765632016-12-12 22:26:34 -0800549
550 // Move child to a proper position, as some restriction for position might apply.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800551 positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
Andrii Kuliand2765632016-12-12 22:26:34 -0800552 }
553
Yunfan Chen279f5582018-12-12 15:24:50 -0800554 void positionChildAt(Task child, int position) {
555 if (DEBUG_STACK) {
556 Slog.i(TAG_WM, "positionChildAt: positioning task=" + child + " at " + position);
557 }
558 if (child == null) {
559 if (DEBUG_STACK) {
560 Slog.i(TAG_WM, "positionChildAt: could not find task=" + this);
561 }
562 return;
563 }
564 child.positionAt(position);
565 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
566 }
567
568 void positionChildAtTop(Task child, boolean includingParents) {
569 if (child == null) {
570 // TODO: Fix the call-points that cause this to happen.
571 return;
572 }
573
574 positionChildAt(POSITION_TOP, child, includingParents);
575
576 final DisplayContent displayContent = getDisplayContent();
577 if (displayContent.mAppTransition.isTransitionSet()) {
578 child.setSendingToBottom(false);
579 }
580 displayContent.layoutAndAssignWindowLayersIfNeeded();
581 }
582
583 void positionChildAtBottom(Task child, boolean includingParents) {
584 if (child == null) {
585 // TODO: Fix the call-points that cause this to happen.
586 return;
587 }
588
589 positionChildAt(POSITION_BOTTOM, child, includingParents);
590
591 if (getDisplayContent().mAppTransition.isTransitionSet()) {
592 child.setSendingToBottom(true);
593 }
594 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
595 }
596
Andrii Kuliand2765632016-12-12 22:26:34 -0800597 @Override
598 void positionChildAt(int position, Task child, boolean includingParents) {
599 positionChildAt(position, child, includingParents, child.showForAllUsers());
600 }
601
602 /**
603 * Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800604 * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive
Andrii Kuliand2765632016-12-12 22:26:34 -0800605 * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}.
606 */
607 private void positionChildAt(int position, Task child, boolean includingParents,
608 boolean showForAllUsers) {
609 final int targetPosition = findPositionForTask(child, position, showForAllUsers,
610 false /* addingNew */);
611 super.positionChildAt(targetPosition, child, includingParents);
612
613 // Log positioning.
614 if (DEBUG_TASK_MOVEMENT)
615 Slog.d(TAG_WM, "positionTask: task=" + this + " position=" + position);
616
617 final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
618 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700619 }
620
Yunfan Chen279f5582018-12-12 15:24:50 -0800621 void reparent(int displayId, Rect outStackBounds, boolean onTop) {
622 final DisplayContent targetDc = mWmService.mRoot.getDisplayContent(displayId);
623 if (targetDc == null) {
624 throw new IllegalArgumentException("Trying to move stackId=" + mStackId
625 + " to unknown displayId=" + displayId);
626 }
627
628 targetDc.moveStackToDisplay(this, onTop);
629 if (matchParentBounds()) {
630 outStackBounds.setEmpty();
631 } else {
632 getRawBounds(outStackBounds);
633 }
634 }
635
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700636 // 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 -0800637 // have to do complicated things like we are doing in this method.
638 private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
639 boolean addingNew) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700640 final boolean canShowTask =
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800641 showForAllUsers || mWmService.isCurrentProfileLocked(task.mUserId);
Andrii Kuliand2765632016-12-12 22:26:34 -0800642
643 final int stackSize = mChildren.size();
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700644 int minPosition = 0;
Andrii Kuliand2765632016-12-12 22:26:34 -0800645 int maxPosition = addingNew ? stackSize : stackSize - 1;
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700646
647 if (canShowTask) {
648 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700649 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700650 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700651 }
Evan Rosky9c448172017-11-02 14:19:27 -0700652
653 // preserve POSITION_BOTTOM/POSITION_TOP positions if they are still valid.
654 if (targetPosition == POSITION_BOTTOM && minPosition == 0) {
655 return POSITION_BOTTOM;
656 } else if (targetPosition == POSITION_TOP
657 && maxPosition == (addingNew ? stackSize : stackSize - 1)) {
658 return POSITION_TOP;
659 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700660 // Reset position based on minimum/maximum possible positions.
Andrii Kuliand2765632016-12-12 22:26:34 -0800661 return Math.min(Math.max(targetPosition, minPosition), maxPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700662 }
663
664 /** Calculate the minimum possible position for a task that can be shown to the user.
665 * The minimum position will be above all other tasks that can't be shown.
666 * @param minPosition The minimum position the caller is suggesting.
667 * We will start adjusting up from here.
668 * @param size The size of the current task list.
669 */
670 private int computeMinPosition(int minPosition, int size) {
671 while (minPosition < size) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700672 final Task tmpTask = mChildren.get(minPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700673 final boolean canShowTmpTask =
674 tmpTask.showForAllUsers()
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800675 || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700676 if (canShowTmpTask) {
677 break;
678 }
679 minPosition++;
680 }
681 return minPosition;
682 }
683
684 /** Calculate the maximum possible position for a task that can't be shown to the user.
685 * The maximum position will be below all other tasks that can be shown.
686 * @param maxPosition The maximum position the caller is suggesting.
687 * We will start adjusting down from here.
688 */
689 private int computeMaxPosition(int maxPosition) {
690 while (maxPosition > 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800691 final Task tmpTask = mChildren.get(maxPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700692 final boolean canShowTmpTask =
693 tmpTask.showForAllUsers()
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800694 || mWmService.isCurrentProfileLocked(tmpTask.mUserId);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700695 if (!canShowTmpTask) {
696 break;
697 }
698 maxPosition--;
699 }
700 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800701 }
702
Craig Mautner00af9fe2013-03-25 09:13:41 -0700703 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800704 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
705 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700706 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700707 */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700708 @Override
709 void removeChild(Task task) {
710 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700711
712 super.removeChild(task);
Andrii Kuliand2765632016-12-12 22:26:34 -0800713 task.mStack = null;
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700714
Craig Mautnerdf88d732014-01-27 09:21:32 -0800715 if (mDisplayContent != null) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700716 if (mChildren.isEmpty()) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800717 getParent().positionChildAt(POSITION_BOTTOM, this, false /* includingParents */);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800718 }
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700719 mDisplayContent.setLayoutNeeded();
Craig Mautner04a0ea62014-01-13 12:51:26 -0800720 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800721 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
722 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Bryce Lee6d410262017-02-28 15:30:17 -0800723 if (wtoken.getTask() == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800724 wtoken.mIsExiting = false;
725 mExitingAppTokens.remove(appNdx);
726 }
727 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800728 }
729
Wale Ogunwale61911492017-10-11 08:50:50 -0700730 @Override
731 public void onConfigurationChanged(Configuration newParentConfig) {
732 final int prevWindowingMode = getWindowingMode();
Jorim Jaggi1a6d98b2018-01-08 16:23:00 +0100733 super.onConfigurationChanged(newParentConfig);
734
chaviwe07246a2017-12-12 16:18:29 -0800735 // Only need to update surface size here since the super method will handle updating
736 // surface position.
737 updateSurfaceSize(getPendingTransaction());
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800738 final int windowingMode = getWindowingMode();
Kazuki Takisef85197b2018-06-18 18:18:36 +0900739 final boolean isAlwaysOnTop = isAlwaysOnTop();
chaviwe07246a2017-12-12 16:18:29 -0800740
Kazuki Takisef85197b2018-06-18 18:18:36 +0900741 if (mDisplayContent == null) {
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800742 return;
Wale Ogunwale61911492017-10-11 08:50:50 -0700743 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900744
745 if (prevWindowingMode != windowingMode) {
746 mDisplayContent.onStackWindowingModeChanged(this);
Kazuki Takisef85197b2018-06-18 18:18:36 +0900747
Evan Roskyc5abbd82018-10-05 16:02:19 -0700748 if (inSplitScreenSecondaryWindowingMode()) {
749 // When the stack is resized due to entering split screen secondary, offset the
750 // windows to compensate for the new stack position.
751 forAllWindows(w -> {
752 w.mWinAnimator.setOffsetPositionForStackResize(true);
753 }, true);
754 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900755 }
Wale Ogunwale61911492017-10-11 08:50:50 -0700756 }
757
chaviwe07246a2017-12-12 16:18:29 -0800758 private void updateSurfaceBounds() {
chaviw2f0567b2018-01-29 16:22:02 -0800759 updateSurfaceSize(getPendingTransaction());
760 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800761 scheduleAnimation();
762 }
763
Robert Carr32bcb102018-01-29 15:03:23 -0800764 /**
765 * Calculate an amount by which to expand the stack bounds in each direction.
766 * Used to make room for shadows in the pinned windowing mode.
767 */
768 int getStackOutset() {
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700769 DisplayContent displayContent = getDisplayContent();
770 if (inPinnedWindowingMode() && displayContent != null) {
771 final DisplayMetrics displayMetrics = displayContent.getDisplayMetrics();
Robert Carr74a66a22018-02-23 12:17:51 -0800772
773 // We multiply by two to match the client logic for converting view elevation
774 // to insets, as in {@link WindowManager.LayoutParams#setSurfaceInsets}
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800775 return (int)Math.ceil(mWmService.dipToPixel(PINNED_WINDOWING_MODE_ELEVATION_IN_DIP,
Robert Carr74a66a22018-02-23 12:17:51 -0800776 displayMetrics) * 2);
Robert Carr32bcb102018-01-29 15:03:23 -0800777 }
778 return 0;
779 }
780
Riddle Hsu6619acb2019-02-20 19:12:57 +0800781 @Override
782 void getRelativeDisplayedPosition(Point outPos) {
783 super.getRelativeDisplayedPosition(outPos);
784 final int outset = getStackOutset();
785 outPos.x -= outset;
786 outPos.y -= outset;
787 }
788
chaviwe07246a2017-12-12 16:18:29 -0800789 private void updateSurfaceSize(SurfaceControl.Transaction transaction) {
790 if (mSurfaceControl == null) {
791 return;
792 }
793
Evan Roskyed6767f2018-10-26 17:21:06 -0700794 final Rect stackBounds = getDisplayedBounds();
Robert Carr32bcb102018-01-29 15:03:23 -0800795 int width = stackBounds.width();
796 int height = stackBounds.height();
797
798 final int outset = getStackOutset();
799 width += 2*outset;
800 height += 2*outset;
801
chaviw3e751af2018-01-11 11:22:39 -0800802 if (width == mLastSurfaceSize.x && height == mLastSurfaceSize.y) {
803 return;
804 }
Evan Rosky1c66f442019-04-30 16:02:58 -0700805 if (getWindowConfiguration().tasksAreFloating()) {
806 // Don't crop freeform windows to the stack.
807 transaction.setWindowCrop(mSurfaceControl, -1, -1);
808 } else {
809 transaction.setWindowCrop(mSurfaceControl, width, height);
810 }
chaviw3e751af2018-01-11 11:22:39 -0800811 mLastSurfaceSize.set(width, height);
chaviwe07246a2017-12-12 16:18:29 -0800812 }
813
Riddle Hsu6619acb2019-02-20 19:12:57 +0800814 @VisibleForTesting
815 Point getLastSurfaceSize() {
816 return mLastSurfaceSize;
817 }
818
Wale Ogunwale61911492017-10-11 08:50:50 -0700819 @Override
Wale Ogunwale02319a62016-09-26 15:21:22 -0700820 void onDisplayChanged(DisplayContent dc) {
Garfield Tan2f145f22018-11-01 15:27:03 -0700821 if (mDisplayContent != null && mDisplayContent != dc) {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700822 throw new IllegalStateException("onDisplayChanged: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800823 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800824
Tiger Huanged6794e2019-05-07 20:07:59 +0800825 super.onDisplayChanged(dc);
Robert Carrf59b8dd2017-10-02 18:58:36 -0700826
Evan Roskyc5abbd82018-10-05 16:02:19 -0700827 updateSurfaceBounds();
Garfield Tanf80d4202018-11-15 11:17:06 -0800828 if (mAnimationBackgroundSurface == null) {
Chavi Weingarten6ef9cc62019-02-07 16:28:45 +0000829 mAnimationBackgroundSurface = makeChildSurface(null).setColorLayer()
Garfield Tan2f145f22018-11-01 15:27:03 -0700830 .setName("animation background stackId=" + mStackId)
831 .build();
832 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800833 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700834
Matthew Ngaa2b6202017-02-10 14:48:21 -0800835 /**
836 * Determines the stack and task bounds of the other stack when in docked mode. The current task
837 * bounds is passed in but depending on the stack, the task and stack must match. Only in
838 * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds
839 * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds
840 * is calculated and is also used for its task bounds.
841 * If any of the out bounds are empty, it represents default bounds
842 *
843 * @param currentTempTaskBounds the current task bounds of the other stack
844 * @param outStackBounds the calculated stack bounds of the other stack
845 * @param outTempTaskBounds the calculated task bounds of the other stack
Matthew Ngaa2b6202017-02-10 14:48:21 -0800846 */
Evan Roskyc5abbd82018-10-05 16:02:19 -0700847 void getStackDockedModeBoundsLocked(Configuration parentConfig, Rect dockedBounds,
848 Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds) {
Matthew Ngaa2b6202017-02-10 14:48:21 -0800849 outTempTaskBounds.setEmpty();
850
Evan Roskyc5abbd82018-10-05 16:02:19 -0700851 if (dockedBounds == null || dockedBounds.isEmpty()) {
852 // Calculate the primary docked bounds.
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800853 final boolean dockedOnTopOrLeft = mWmService.mDockedStackCreateMode
Evan Roskyc5abbd82018-10-05 16:02:19 -0700854 == SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
855 getStackDockedModeBounds(parentConfig,
856 true /* primary */, outStackBounds, dockedBounds,
857 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
858 return;
859 }
860 final int dockedSide = getDockSide(parentConfig, dockedBounds);
861
Matthew Ngaa2b6202017-02-10 14:48:21 -0800862 // When the home stack is resizable, should always have the same stack and task bounds
Wale Ogunwale68278562017-09-23 17:13:55 -0700863 if (isActivityTypeHome()) {
Winson Chungf7fb5e32017-05-23 17:47:05 -0700864 final Task homeTask = findHomeTask();
865 if (homeTask != null && homeTask.isResizeable()) {
Wale Ogunwale649c1602017-04-24 10:15:31 -0700866 // Calculate the home stack bounds when in docked mode and the home stack is
867 // resizeable.
868 getDisplayContent().mDividerControllerLocked
Evan Roskyc5abbd82018-10-05 16:02:19 -0700869 .getHomeStackBoundsInDockedMode(parentConfig,
870 dockedSide, outStackBounds);
Wale Ogunwale649c1602017-04-24 10:15:31 -0700871 } else {
872 // Home stack isn't resizeable, so don't specify stack bounds.
873 outStackBounds.setEmpty();
874 }
875
Matthew Ngaa2b6202017-02-10 14:48:21 -0800876 outTempTaskBounds.set(outStackBounds);
877 return;
878 }
879
880 // When minimized state, the stack bounds for all non-home and docked stack bounds should
881 // match the passed task bounds
882 if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) {
883 outStackBounds.set(currentTempTaskBounds);
884 return;
Matthew Nge15352e2016-12-20 15:36:29 -0800885 }
886
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700887 if (dockedSide == DOCKED_INVALID) {
888 // Not sure how you got here...Only thing we can do is return current bounds.
Evan Roskyc5abbd82018-10-05 16:02:19 -0700889 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack");
Bryce Leef3c6a472017-11-14 14:53:06 -0800890 outStackBounds.set(getRawBounds());
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700891 return;
892 }
893
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800894 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Evan Roskyc5abbd82018-10-05 16:02:19 -0700895 getStackDockedModeBounds(parentConfig,
896 false /* primary */, outStackBounds, dockedBounds,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100897 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700898 }
899
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700900 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700901 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Evan Roskyc5abbd82018-10-05 16:02:19 -0700902 * @param parentConfig The parent configuration.
903 * @param primary {@code true} if getting the primary stack bounds.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700904 * @param outBounds Output bounds that should be used for the stack.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700905 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700906 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
907 * close to the side of the dock.
908 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700909 */
Evan Roskyc5abbd82018-10-05 16:02:19 -0700910 private void getStackDockedModeBounds(Configuration parentConfig, boolean primary,
911 Rect outBounds, Rect dockedBounds, int dockDividerWidth,
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700912 boolean dockOnTopOrLeft) {
Evan Roskyc5abbd82018-10-05 16:02:19 -0700913 final Rect displayRect = parentConfig.windowConfiguration.getBounds();
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700914 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700915
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700916 outBounds.set(displayRect);
Evan Roskyc5abbd82018-10-05 16:02:19 -0700917 if (primary) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800918 if (mWmService.mDockedStackCreateBounds != null) {
919 outBounds.set(mWmService.mDockedStackCreateBounds);
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800920 return;
921 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100922
923 // The initial bounds of the docked stack when it is created about half the screen space
924 // and its bounds can be adjusted after that. The bounds of all other stacks are
925 // adjusted to occupy whatever screen space the docked stack isn't occupying.
Evan Roskyc5abbd82018-10-05 16:02:19 -0700926 final DisplayCutout displayCutout = mDisplayContent.getDisplayInfo().displayCutout;
Tiger Huang7c610aa2018-10-27 00:01:01 +0800927 mDisplayContent.getDisplayPolicy().getStableInsetsLw(
928 parentConfig.windowConfiguration.getRotation(),
Evan Roskyc5abbd82018-10-05 16:02:19 -0700929 displayRect.width(), displayRect.height(), displayCutout, mTmpRect2);
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800930 final int position = new DividerSnapAlgorithm(mWmService.mContext.getResources(),
Evan Roskyc5abbd82018-10-05 16:02:19 -0700931 displayRect.width(),
932 displayRect.height(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100933 dockDividerWidth,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700934 parentConfig.orientation == ORIENTATION_PORTRAIT,
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100935 mTmpRect2).getMiddleTarget().position;
936
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700937 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700938 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100939 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700940 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100941 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700942 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700943 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700944 if (splitHorizontally) {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700945 outBounds.left = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700946 } else {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700947 outBounds.top = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700948 }
949 }
950 return;
951 }
952
953 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700954 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700955 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700956 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700957 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700958 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700959 }
960 } else {
961 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700962 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700963 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700964 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700965 }
966 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800967 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700968 }
969
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800970 void resetDockedStackToMiddle() {
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700971 if (inSplitScreenPrimaryWindowingMode()) {
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800972 throw new IllegalStateException("Not a docked stack=" + this);
973 }
974
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800975 mWmService.mDockedStackCreateBounds = null;
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800976
977 final Rect bounds = new Rect();
Matthew Nge15352e2016-12-20 15:36:29 -0800978 final Rect tempBounds = new Rect();
Evan Roskyc5abbd82018-10-05 16:02:19 -0700979 TaskStack dockedStack = mDisplayContent.getSplitScreenPrimaryStackIgnoringVisibility();
980 Rect dockedBounds =
981 (dockedStack == null || dockedStack == this) ? null : dockedStack.getRawBounds();
982 getStackDockedModeBoundsLocked(mDisplayContent.getConfiguration(), dockedBounds,
983 null /* currentTempTaskBounds */, bounds, tempBounds);
Yunfan Chen279f5582018-12-12 15:24:50 -0800984 mActivityStack.requestResize(bounds);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800985 }
986
Wale Ogunwale10124582016-09-15 20:25:50 -0700987 @Override
988 void removeIfPossible() {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100989 if (isSelfOrChildAnimating()) {
Wale Ogunwale10124582016-09-15 20:25:50 -0700990 mDeferRemoval = true;
991 return;
992 }
993 removeImmediately();
994 }
995
996 @Override
Yunfan Chen279f5582018-12-12 15:24:50 -0800997 void removeImmediately() {
998 if (mActivityStack != null) {
999 mActivityStack.unregisterConfigurationChangeListener(this);
1000 }
1001 super.removeImmediately();
1002 }
1003
1004 @Override
Riddle Hsu3a4bb612019-01-31 00:02:22 +08001005 void onParentChanged() {
1006 super.onParentChanged();
Robert Carrb1579c82017-09-05 14:54:47 -07001007
Wale Ogunwale61911492017-10-11 08:50:50 -07001008 if (getParent() != null || mDisplayContent == null) {
1009 return;
1010 }
Wale Ogunwale10124582016-09-15 20:25:50 -07001011
Craig Mautnerdf88d732014-01-27 09:21:32 -08001012 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -07001013
1014 if (mAnimationBackgroundSurface != null) {
chaviwdd5bde02019-06-07 16:33:50 -07001015 mWmService.mTransactionFactory.make().remove(mAnimationBackgroundSurface).apply();
Wale Ogunwale10124582016-09-15 20:25:50 -07001016 mAnimationBackgroundSurface = null;
1017 }
Wale Ogunwale10124582016-09-15 20:25:50 -07001018
Andrii Kulian839def92016-11-02 10:58:58 -07001019 mDisplayContent = null;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001020 mWmService.mWindowPlacerLocked.requestTraversal();
Craig Mautner00af9fe2013-03-25 09:13:41 -07001021 }
1022
Craig Mautner05d29032013-05-03 13:40:13 -07001023 void resetAnimationBackgroundAnimator() {
1024 mAnimationBackgroundAnimator = null;
Robert Carrf59b8dd2017-10-02 18:58:36 -07001025 hideAnimationSurface();
Craig Mautner05d29032013-05-03 13:40:13 -07001026 }
1027
Craig Mautner05d29032013-05-03 13:40:13 -07001028 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
Jorim Jaggi35d328a2018-08-14 17:00:20 +02001029 if (mAnimationBackgroundAnimator == null) {
Craig Mautner05d29032013-05-03 13:40:13 -07001030 mAnimationBackgroundAnimator = winAnimator;
Robert Carrf59b8dd2017-10-02 18:58:36 -07001031 showAnimationSurface(((color >> 24) & 0xff) / 255f);
Craig Mautner05d29032013-05-03 13:40:13 -07001032 }
1033 }
1034
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001035 // TODO: Should each user have there own stacks?
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001036 @Override
Wale Ogunwale498e8c92015-02-13 09:42:46 -08001037 void switchUser() {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001038 super.switchUser();
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001039 int top = mChildren.size();
Craig Mautnerac6f8432013-07-17 13:24:59 -07001040 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001041 Task task = mChildren.get(taskNdx);
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001042 if (mWmService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001043 mChildren.remove(taskNdx);
1044 mChildren.add(task);
Craig Mautnerac6f8432013-07-17 13:24:59 -07001045 --top;
1046 }
1047 }
1048 }
1049
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001050 /**
1051 * Adjusts the stack bounds if the IME is visible.
1052 *
1053 * @param imeWin The IME window.
lumark72aeda02018-12-18 21:34:04 +08001054 * @param keepLastAmount Use {@code true} to keep the last adjusted amount from
1055 * {@link DockedStackDividerController} for adjusting the stack bounds,
1056 * Use {@code false} to reset adjusted amount as 0.
1057 * @see #updateAdjustForIme(float, float, boolean)
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001058 */
lumark72aeda02018-12-18 21:34:04 +08001059 void setAdjustedForIme(WindowState imeWin, boolean keepLastAmount) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001060 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -07001061 mImeGoingAway = false;
lumark72aeda02018-12-18 21:34:04 +08001062 if (!mAdjustedForIme || keepLastAmount) {
Jorim Jaggiff71d202016-04-14 13:12:36 -07001063 mAdjustedForIme = true;
lumark72aeda02018-12-18 21:34:04 +08001064 DockedStackDividerController controller = getDisplayContent().mDividerControllerLocked;
1065 final float adjustImeAmount = keepLastAmount ? controller.mLastAnimationProgress : 0f;
1066 final float adjustDividerAmount = keepLastAmount ? controller.mLastDividerProgress : 0f;
1067 updateAdjustForIme(adjustImeAmount, adjustDividerAmount, true /* force */);
Jorim Jaggiff71d202016-04-14 13:12:36 -07001068 }
Chong Zhangbaba7832016-03-24 10:21:26 -07001069 }
1070
1071 boolean isAdjustedForIme() {
Chong Zhang5117e272016-05-03 12:47:34 -07001072 return mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -07001073 }
Chong Zhangbaba7832016-03-24 10:21:26 -07001074
1075 boolean isAnimatingForIme() {
1076 return mImeWin != null && mImeWin.isAnimatingLw();
1077 }
1078
1079 /**
1080 * Update the stack's bounds (crop or position) according to the IME window's
1081 * current position. When IME window is animated, the bottom stack is animated
1082 * together to track the IME window's current position, and the top stack is
1083 * cropped as necessary.
1084 *
1085 * @return true if a traversal should be performed after the adjustment.
1086 */
Chong Zhangf347ab52016-04-18 21:02:01 -07001087 boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
1088 if (adjustAmount != mAdjustImeAmount
1089 || adjustDividerAmount != mAdjustDividerAmount || force) {
Jorim Jaggieb88d832016-04-13 20:17:43 -07001090 mAdjustImeAmount = adjustAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -07001091 mAdjustDividerAmount = adjustDividerAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -07001092 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +02001093 return isVisible();
Jorim Jaggieb88d832016-04-13 20:17:43 -07001094 } else {
1095 return false;
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001096 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001097 }
1098
1099 /**
1100 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -07001101 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
1102 * animations; otherwise, set flag and animates the window away together
1103 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001104 */
Chong Zhangbaba7832016-03-24 10:21:26 -07001105 void resetAdjustedForIme(boolean adjustBoundsNow) {
1106 if (adjustBoundsNow) {
1107 mImeWin = null;
Chong Zhangbaba7832016-03-24 10:21:26 -07001108 mImeGoingAway = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -07001109 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -07001110 mAdjustDividerAmount = 0f;
Jorim Jaggif93ac2b2017-10-25 15:20:24 +02001111 if (!mAdjustedForIme) {
1112 return;
1113 }
1114 mAdjustedForIme = false;
Chong Zhangbaba7832016-03-24 10:21:26 -07001115 updateAdjustedBounds();
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001116 mWmService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
Chong Zhangbaba7832016-03-24 10:21:26 -07001117 } else {
1118 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001119 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001120 }
1121
1122 /**
1123 * Sets the amount how much we currently minimize our stack.
1124 *
1125 * @param minimizeAmount The amount, between 0 and 1.
1126 * @return Whether the amount has changed and a layout is needed.
1127 */
1128 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
1129 if (minimizeAmount != mMinimizeAmount) {
1130 mMinimizeAmount = minimizeAmount;
1131 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +02001132 return isVisible();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001133 } else {
1134 return false;
1135 }
1136 }
1137
Matthew Nge15352e2016-12-20 15:36:29 -08001138 boolean shouldIgnoreInput() {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001139 return isAdjustedForMinimizedDockedStack() ||
1140 (inSplitScreenPrimaryWindowingMode() && isMinimizedDockAndHomeStackResizable());
Jorim Jaggi409635b2016-04-01 15:32:28 -07001141 }
1142
Jorim Jaggiff71d202016-04-14 13:12:36 -07001143 /**
1144 * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
1145 * to the list of to be drawn windows the service is waiting for.
1146 */
1147 void beginImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001148 for (int j = mChildren.size() - 1; j >= 0; j--) {
1149 final Task task = mChildren.get(j);
Wale Ogunwale44f21802016-09-02 12:49:48 -07001150 if (task.hasContentToDisplay()) {
Jorim Jaggiff71d202016-04-14 13:12:36 -07001151 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001152 task.setWaitingForDrawnIfResizingChanged();
Jorim Jaggiff71d202016-04-14 13:12:36 -07001153 }
1154 }
1155 }
1156
1157 /**
1158 * Resets the resizing state of all windows.
1159 */
1160 void endImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001161 for (int j = mChildren.size() - 1; j >= 0; j--) {
1162 mChildren.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Jorim Jaggiff71d202016-04-14 13:12:36 -07001163 }
1164 }
1165
Chong Zhang198afac2016-04-15 12:03:11 -07001166 int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
1167 return displayContentRect.top + (int)
1168 ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
1169 }
1170
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001171 private boolean adjustForIME(final WindowState imeWin) {
lumarkbcc316e2018-12-25 21:37:05 +08001172 // To prevent task stack resize animation may flicking when playing app transition
1173 // animation & IME window enter animation in parallel, we need to make sure app
1174 // transition is done and then adjust task size for IME, skip the new adjusted frame when
1175 // app transition is still running.
1176 if (getDisplayContent().mAppTransition.isRunning()) {
1177 return false;
1178 }
1179
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001180 final int dockedSide = getDockSide();
1181 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001182 if (imeWin == null || !dockedTopOrBottom) {
1183 return false;
1184 }
1185
Wale Ogunwaledb506192017-12-08 10:57:32 -08001186 final Rect displayStableRect = mTmpRect;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001187 final Rect contentBounds = mTmpRect2;
1188
1189 // Calculate the content bounds excluding the area occupied by IME
Wale Ogunwaledb506192017-12-08 10:57:32 -08001190 getDisplayContent().getStableRect(displayStableRect);
1191 contentBounds.set(displayStableRect);
Jorim Jaggi5ac2ba22016-04-11 21:14:12 -07001192 int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -07001193
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001194 imeTop += imeWin.getGivenContentInsetsLw().top;
1195 if (contentBounds.bottom > imeTop) {
1196 contentBounds.bottom = imeTop;
1197 }
1198
Wale Ogunwaledb506192017-12-08 10:57:32 -08001199 final int yOffset = displayStableRect.bottom - contentBounds.bottom;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001200
Chong Zhang198afac2016-04-15 12:03:11 -07001201 final int dividerWidth =
1202 getDisplayContent().mDividerControllerLocked.getContentWidth();
1203 final int dividerWidthInactive =
1204 getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
1205
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001206 if (dockedSide == DOCKED_TOP) {
1207 // If this stack is docked on top, we make it smaller so the bottom stack is not
Chong Zhang198afac2016-04-15 12:03:11 -07001208 // occluded by IME. We shift its bottom up by the height of the IME, but
1209 // leaves at least 30% of the top stack visible.
1210 final int minTopStackBottom =
Wale Ogunwaledb506192017-12-08 10:57:32 -08001211 getMinTopStackBottom(displayStableRect, getRawBounds().bottom);
Chong Zhang198afac2016-04-15 12:03:11 -07001212 final int bottom = Math.max(
Bryce Leef3c6a472017-11-14 14:53:06 -08001213 getRawBounds().bottom - yOffset + dividerWidth - dividerWidthInactive,
Chong Zhang198afac2016-04-15 12:03:11 -07001214 minTopStackBottom);
Bryce Leef3c6a472017-11-14 14:53:06 -08001215 mTmpAdjustedBounds.set(getRawBounds());
1216 mTmpAdjustedBounds.bottom = (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount)
1217 * getRawBounds().bottom);
1218 mFullyAdjustedImeBounds.set(getRawBounds());
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001219 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -07001220 // When the stack is on bottom and has no focus, it's only adjusted for divider width.
1221 final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
1222
1223 // When the stack is on bottom and has focus, it needs to be moved up so as to
1224 // not occluded by IME, and at the same time adjusted for divider width.
1225 // We try to move it up by the height of the IME window, but only to the extent
1226 // that leaves at least 30% of the top stack visible.
1227 // 'top' is where the top of bottom stack will move to in this case.
Bryce Leef3c6a472017-11-14 14:53:06 -08001228 final int topBeforeImeAdjust =
1229 getRawBounds().top - dividerWidth + dividerWidthInactive;
Chong Zhangf347ab52016-04-18 21:02:01 -07001230 final int minTopStackBottom =
Wale Ogunwaledb506192017-12-08 10:57:32 -08001231 getMinTopStackBottom(displayStableRect,
Bryce Leef3c6a472017-11-14 14:53:06 -08001232 getRawBounds().top - dividerWidth);
Chong Zhangf347ab52016-04-18 21:02:01 -07001233 final int top = Math.max(
Bryce Leef3c6a472017-11-14 14:53:06 -08001234 getRawBounds().top - yOffset, minTopStackBottom + dividerWidthInactive);
Chong Zhang198afac2016-04-15 12:03:11 -07001235
Bryce Leef3c6a472017-11-14 14:53:06 -08001236 mTmpAdjustedBounds.set(getRawBounds());
Chong Zhangf347ab52016-04-18 21:02:01 -07001237 // Account for the adjustment for IME and divider width separately.
1238 // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
1239 // and dividerWidthDelta is due to divider width change only.
Bryce Leef3c6a472017-11-14 14:53:06 -08001240 mTmpAdjustedBounds.top = getRawBounds().top +
Chong Zhangf347ab52016-04-18 21:02:01 -07001241 (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
1242 mAdjustDividerAmount * dividerWidthDelta);
Bryce Leef3c6a472017-11-14 14:53:06 -08001243 mFullyAdjustedImeBounds.set(getRawBounds());
Jorim Jaggieb88d832016-04-13 20:17:43 -07001244 mFullyAdjustedImeBounds.top = top;
Bryce Leef3c6a472017-11-14 14:53:06 -08001245 mFullyAdjustedImeBounds.bottom = top + getRawBounds().height();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001246 }
1247 return true;
1248 }
1249
1250 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
1251 final int dockSide = getDockSide();
1252 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
1253 return false;
1254 }
1255
1256 if (dockSide == DOCKED_TOP) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001257 mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001258 int topInset = mTmpRect.top;
Bryce Leef3c6a472017-11-14 14:53:06 -08001259 mTmpAdjustedBounds.set(getRawBounds());
1260 mTmpAdjustedBounds.bottom = (int) (minimizeAmount * topInset + (1 - minimizeAmount)
1261 * getRawBounds().bottom);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001262 } else if (dockSide == DOCKED_LEFT) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001263 mTmpAdjustedBounds.set(getRawBounds());
1264 final int width = getRawBounds().width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001265 mTmpAdjustedBounds.right =
1266 (int) (minimizeAmount * mDockedStackMinimizeThickness
Bryce Leef3c6a472017-11-14 14:53:06 -08001267 + (1 - minimizeAmount) * getRawBounds().right);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001268 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001269 } else if (dockSide == DOCKED_RIGHT) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001270 mTmpAdjustedBounds.set(getRawBounds());
1271 mTmpAdjustedBounds.left = (int) (minimizeAmount *
1272 (getRawBounds().right - mDockedStackMinimizeThickness)
1273 + (1 - minimizeAmount) * getRawBounds().left);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001274 }
1275 return true;
1276 }
1277
Matthew Nge15352e2016-12-20 15:36:29 -08001278 private boolean isMinimizedDockAndHomeStackResizable() {
1279 return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
1280 && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
1281 }
1282
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001283 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -08001284 * @return the distance in pixels how much the stack gets minimized from it's original size
1285 */
1286 int getMinimizeDistance() {
1287 final int dockSide = getDockSide();
1288 if (dockSide == DOCKED_INVALID) {
1289 return 0;
1290 }
1291
1292 if (dockSide == DOCKED_TOP) {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001293 mWmService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggif97ed922016-02-18 18:57:07 -08001294 int topInset = mTmpRect.top;
Bryce Leef3c6a472017-11-14 14:53:06 -08001295 return getRawBounds().bottom - topInset;
Jorim Jaggif97ed922016-02-18 18:57:07 -08001296 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001297 return getRawBounds().width() - mDockedStackMinimizeThickness;
Jorim Jaggif97ed922016-02-18 18:57:07 -08001298 } else {
1299 return 0;
1300 }
1301 }
1302
1303 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001304 * Updates the adjustment depending on it's current state.
1305 */
Chong Zhang5117e272016-05-03 12:47:34 -07001306 private void updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001307 boolean adjust = false;
1308 if (mMinimizeAmount != 0f) {
1309 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1310 } else if (mAdjustedForIme) {
1311 adjust = adjustForIME(mImeWin);
1312 }
1313 if (!adjust) {
1314 mTmpAdjustedBounds.setEmpty();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001315 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001316 setAdjustedBounds(mTmpAdjustedBounds);
Chong Zhang198afac2016-04-15 12:03:11 -07001317
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001318 final boolean isImeTarget = (mWmService.getImeFocusStackLocked() == this);
Chong Zhangf347ab52016-04-18 21:02:01 -07001319 if (mAdjustedForIme && adjust && !isImeTarget) {
1320 final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
1321 * IME_ADJUST_DIM_AMOUNT;
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001322 mWmService.setResizeDimLayer(true, getWindowingMode(), alpha);
Chong Zhang198afac2016-04-15 12:03:11 -07001323 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001324 }
1325
Chong Zhang5117e272016-05-03 12:47:34 -07001326 void applyAdjustForImeIfNeeded(Task task) {
1327 if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) {
1328 return;
1329 }
1330
Bryce Leef3c6a472017-11-14 14:53:06 -08001331 final Rect insetBounds = mImeGoingAway ? getRawBounds() : mFullyAdjustedImeBounds;
Chong Zhang5117e272016-05-03 12:47:34 -07001332 task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001333 mDisplayContent.setLayoutNeeded();
Chong Zhang5117e272016-05-03 12:47:34 -07001334 }
1335
Bryce Leef3c6a472017-11-14 14:53:06 -08001336
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001337 boolean isAdjustedForMinimizedDockedStack() {
1338 return mMinimizeAmount != 0f;
1339 }
1340
Winson Chungd41f71d2018-03-16 15:26:07 -07001341 /**
1342 * @return {@code true} if we have a {@link Task} that is animating (currently only used for the
1343 * recents animation); {@code false} otherwise.
1344 */
1345 boolean isTaskAnimating() {
1346 for (int j = mChildren.size() - 1; j >= 0; j--) {
1347 final Task task = mChildren.get(j);
1348 if (task.isTaskAnimating()) {
1349 return true;
1350 }
1351 }
1352 return false;
1353 }
1354
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001355 @CallSuper
1356 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08001357 public void writeToProto(ProtoOutputStream proto, long fieldId,
1358 @WindowTraceLogLevel int logLevel) {
1359 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible()) {
1360 return;
1361 }
1362
Steven Timotiusaf03df62017-07-18 16:56:43 -07001363 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001364 super.writeToProto(proto, WINDOW_CONTAINER, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001365 proto.write(ID, mStackId);
1366 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
Nataniel Borges023ecb52019-01-16 14:15:43 -08001367 mChildren.get(taskNdx).writeToProto(proto, TASKS, logLevel);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001368 }
Bryce Leef3c6a472017-11-14 14:53:06 -08001369 proto.write(FILLS_PARENT, matchParentBounds());
1370 getRawBounds().writeToProto(proto, BOUNDS);
Robert Carrf59b8dd2017-10-02 18:58:36 -07001371 proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurfaceIsShown);
Vishnu Nair04ab4392018-01-10 11:00:06 -08001372 proto.write(DEFER_REMOVAL, mDeferRemoval);
1373 proto.write(MINIMIZE_AMOUNT, mMinimizeAmount);
1374 proto.write(ADJUSTED_FOR_IME, mAdjustedForIme);
1375 proto.write(ADJUST_IME_AMOUNT, mAdjustImeAmount);
1376 proto.write(ADJUST_DIVIDER_AMOUNT, mAdjustDividerAmount);
1377 mAdjustedBounds.writeToProto(proto, ADJUSTED_BOUNDS);
Winson Chung82267ce2018-04-06 16:38:26 -07001378 proto.write(ANIMATING_BOUNDS, mBoundsAnimating);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001379 proto.end(token);
1380 }
1381
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001382 @Override
1383 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001384 pw.println(prefix + "mStackId=" + mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -07001385 pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
Bryce Leef3c6a472017-11-14 14:53:06 -08001386 pw.println(prefix + "mBounds=" + getRawBounds().toShortString());
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001387 if (mMinimizeAmount != 0f) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001388 pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001389 }
1390 if (mAdjustedForIme) {
1391 pw.println(prefix + "mAdjustedForIme=true");
1392 pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
1393 pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
1394 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001395 if (!mAdjustedBounds.isEmpty()) {
1396 pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
1397 }
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001398 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001399 mChildren.get(taskNdx).dump(pw, prefix + " ", dumpAll);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001400 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07001401 if (mAnimationBackgroundSurfaceIsShown) {
1402 pw.println(prefix + "mWindowAnimationBackgroundSurface is shown");
Craig Mautner05d29032013-05-03 13:40:13 -07001403 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001404 if (!mExitingAppTokens.isEmpty()) {
1405 pw.println();
1406 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001407 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001408 WindowToken token = mExitingAppTokens.get(i);
1409 pw.print(" Exiting App #"); pw.print(i);
1410 pw.print(' '); pw.print(token);
1411 pw.println(':');
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001412 token.dump(pw, " ", dumpAll);
Craig Mautnerdc548482014-02-05 13:35:24 -08001413 }
1414 }
Jorim Jaggib8a9cbe2018-03-27 18:02:18 +02001415 mAnimatingAppWindowTokenRegistry.dump(pw, "AnimatingApps:", prefix);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001416 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001417
1418 @Override
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001419 boolean fillsParent() {
Evan Rosky4fb1e912019-03-06 13:54:43 -08001420 return matchParentBounds();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001421 }
1422
1423 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001424 public String toString() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001425 return "{stackId=" + mStackId + " tasks=" + mChildren + "}";
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001426 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001427
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001428 String getName() {
1429 return toShortString();
1430 }
1431
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001432 public String toShortString() {
1433 return "Stack=" + mStackId;
1434 }
1435
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001436 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001437 * For docked workspace (or workspace that's side-by-side to the docked), provides
1438 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001439 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001440 int getDockSide() {
Evan Rosky39b6f232018-10-30 18:35:41 -07001441 return getDockSide(mDisplayContent.getConfiguration(), getRawBounds());
Jorim Jaggi737af722015-12-31 10:42:27 +01001442 }
1443
Matthew Nge8b052a2018-01-16 14:33:47 -08001444 int getDockSideForDisplay(DisplayContent dc) {
Evan Rosky39b6f232018-10-30 18:35:41 -07001445 return getDockSide(dc, dc.getConfiguration(), getRawBounds());
Matthew Nge8b052a2018-01-16 14:33:47 -08001446 }
1447
Evan Rosky39b6f232018-10-30 18:35:41 -07001448 int getDockSide(Configuration parentConfig, Rect bounds) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001449 if (mDisplayContent == null) {
1450 return DOCKED_INVALID;
1451 }
Evan Rosky39b6f232018-10-30 18:35:41 -07001452 return getDockSide(mDisplayContent, parentConfig, bounds);
Matthew Nge8b052a2018-01-16 14:33:47 -08001453 }
1454
Evan Rosky39b6f232018-10-30 18:35:41 -07001455 private int getDockSide(DisplayContent dc, Configuration parentConfig, Rect bounds) {
Evan Rosky39b6f232018-10-30 18:35:41 -07001456 return dc.getDockedDividerController().getDockSide(bounds,
1457 parentConfig.windowConfiguration.getBounds(),
Evan Roskye747c3e2018-10-30 20:06:41 -07001458 parentConfig.orientation, parentConfig.windowConfiguration.getRotation());
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001459 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001460
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001461 boolean hasTaskForUser(int userId) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001462 for (int i = mChildren.size() - 1; i >= 0; i--) {
1463 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001464 if (task.mUserId == userId) {
1465 return true;
1466 }
1467 }
1468 return false;
1469 }
1470
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001471 void findTaskForResizePoint(int x, int y, int delta,
1472 DisplayContent.TaskForResizePointSearchResult results) {
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001473 if (!getWindowConfiguration().canResizeTask()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001474 results.searchDone = true;
1475 return;
1476 }
1477
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001478 for (int i = mChildren.size() - 1; i >= 0; --i) {
1479 final Task task = mChildren.get(i);
Evan Rosky4fb1e912019-03-06 13:54:43 -08001480 if (task.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001481 results.searchDone = true;
1482 return;
1483 }
1484
1485 // We need to use the task's dim bounds (which is derived from the visible bounds of
1486 // its apps windows) for any touch-related tests. Can't use the task's original
1487 // bounds because it might be adjusted to fit the content frame. One example is when
1488 // the task is put to top-left quadrant, the actual visible area would not start at
1489 // (0,0) after it's adjusted for the status bar.
1490 task.getDimBounds(mTmpRect);
1491 mTmpRect.inset(-delta, -delta);
1492 if (mTmpRect.contains(x, y)) {
1493 mTmpRect.inset(delta, delta);
1494
1495 results.searchDone = true;
1496
1497 if (!mTmpRect.contains(x, y)) {
1498 results.taskForResize = task;
1499 return;
1500 }
1501 // User touched inside the task. No need to look further,
1502 // focus transfer will be handled in ACTION_UP.
1503 return;
1504 }
1505 }
1506 }
1507
1508 void setTouchExcludeRegion(Task focusedTask, int delta, Region touchExcludeRegion,
1509 Rect contentRect, Rect postExclude) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001510 for (int i = mChildren.size() - 1; i >= 0; --i) {
1511 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001512 AppWindowToken token = task.getTopVisibleAppToken();
1513 if (token == null || !token.hasContentToDisplay()) {
1514 continue;
1515 }
1516
1517 /**
1518 * Exclusion region is the region that TapDetector doesn't care about.
1519 * Here we want to remove all non-focused tasks from the exclusion region.
1520 * We also remove the outside touch area for resizing for all freeform
1521 * tasks (including the focused).
1522 *
1523 * We save the focused task region once we find it, and add it back at the end.
Matthew Nge15352e2016-12-20 15:36:29 -08001524 *
1525 * If the task is home stack and it is resizable in the minimized state, we want to
1526 * exclude the docked stack from touch so we need the entire screen area and not just a
1527 * small portion which the home stack currently is resized to.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001528 */
1529
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001530 if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) {
Bryce Leef3c6a472017-11-14 14:53:06 -08001531 mDisplayContent.getBounds(mTmpRect);
Matthew Nge15352e2016-12-20 15:36:29 -08001532 } else {
1533 task.getDimBounds(mTmpRect);
1534 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001535
1536 if (task == focusedTask) {
1537 // Add the focused task rect back into the exclude region once we are done
1538 // processing stacks.
1539 postExclude.set(mTmpRect);
1540 }
1541
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001542 final boolean isFreeformed = task.inFreeformWindowingMode();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001543 if (task != focusedTask || isFreeformed) {
1544 if (isFreeformed) {
1545 // If the task is freeformed, enlarge the area to account for outside
1546 // touch area for resize.
1547 mTmpRect.inset(-delta, -delta);
1548 // Intersect with display content rect. If we have system decor (status bar/
1549 // navigation bar), we want to exclude that from the tap detection.
1550 // Otherwise, if the app is partially placed under some system button (eg.
1551 // Recents, Home), pressing that button would cause a full series of
1552 // unwanted transfer focus/resume/pause, before we could go home.
1553 mTmpRect.intersect(contentRect);
1554 }
1555 touchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
1556 }
1557 }
1558 }
1559
Winson Chung8bca9e42017-04-16 15:59:43 -07001560 public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
1561 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001562 synchronized (mWmService.mGlobalLock) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001563 if (mCancelCurrentBoundsAnimation) {
1564 return false;
1565 }
Winson Chung19953ca2017-04-11 11:19:23 -07001566 }
1567
Robert Carr0d00c2e2016-02-29 17:45:02 -08001568 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001569 mWmService.mActivityTaskManager.resizePinnedStack(stackBounds, tempTaskBounds);
Robert Carr0d00c2e2016-02-29 17:45:02 -08001570 } catch (RemoteException e) {
1571 // I don't believe you.
1572 }
1573 return true;
1574 }
1575
Robert Carrecc06b32017-04-18 14:25:10 -07001576 void onAllWindowsDrawn() {
Winson Chunge7ba6862017-05-24 12:13:33 -07001577 if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
Robert Carrecc06b32017-04-18 14:25:10 -07001578 return;
1579 }
1580
lumark588a3e82018-07-20 18:53:54 +08001581 getDisplayContent().mBoundsAnimationController.onAllWindowsDrawn();
Robert Carrecc06b32017-04-18 14:25:10 -07001582 }
1583
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001584 @Override // AnimatesBounds
Tracy Zhou9c675d42019-04-08 00:32:40 -07001585 public boolean onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate,
1586 @BoundsAnimationController.AnimationType int animationType) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001587 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001588 synchronized (mWmService.mGlobalLock) {
Winson Chunga06403d2018-06-28 12:56:53 -07001589 if (!isAttached()) {
1590 // Don't run the animation if the stack is already detached
1591 return false;
1592 }
1593
Winson Chung40a5f932017-04-13 16:39:36 -07001594 mBoundsAnimatingRequested = false;
Robert Carr1ca6a332016-04-11 18:00:43 -07001595 mBoundsAnimating = true;
Tracy Zhou9c675d42019-04-08 00:32:40 -07001596 mAnimationType = animationType;
Robert Carrecc06b32017-04-18 14:25:10 -07001597
1598 // If we are changing UI mode, as in the PiP to fullscreen
1599 // transition, then we need to wait for the window to draw.
1600 if (schedulePipModeChangedCallback) {
1601 forAllWindows((w) -> { w.mWinAnimator.resetDrawState(); },
1602 false /* traverseTopToBottom */);
1603 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001604 }
Winson Chung85d39982017-02-24 15:21:25 -08001605
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001606 if (inPinnedWindowingMode()) {
Winson Chung85d39982017-02-24 15:21:25 -08001607 try {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001608 mWmService.mActivityTaskManager.notifyPinnedStackAnimationStarted();
Winson Chung85d39982017-02-24 15:21:25 -08001609 } catch (RemoteException e) {
1610 // I don't believe you...
1611 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001612
Tracy Zhou9c675d42019-04-08 00:32:40 -07001613 if ((schedulePipModeChangedCallback || animationType == FADE_IN)
1614 && mActivityStack != null) {
Winson Chungab76bbc2017-08-14 13:33:51 -07001615 // We need to schedule the PiP mode change before the animation up. It is possible
1616 // in this case for the animation down to not have been completed, so always
1617 // force-schedule and update to the client to ensure that it is notified that it
1618 // is no longer in picture-in-picture mode
Yunfan Chen279f5582018-12-12 15:24:50 -08001619 mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(null,
1620 forceUpdate);
Winson Chung8bca9e42017-04-16 15:59:43 -07001621 }
Winson Chung85d39982017-02-24 15:21:25 -08001622 }
Winson Chunga06403d2018-06-28 12:56:53 -07001623 return true;
Wale Ogunwalece144522016-02-05 22:51:01 -08001624 }
1625
1626 @Override // AnimatesBounds
Winson Chung8bca9e42017-04-16 15:59:43 -07001627 public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
1628 boolean moveToFullscreen) {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001629 if (inPinnedWindowingMode()) {
Robert Carr18f622f2017-05-08 11:20:43 -07001630 // Update to the final bounds if requested. This is done here instead of in the bounds
1631 // animator to allow us to coordinate this after we notify the PiP mode changed
1632
Yunfan Chen279f5582018-12-12 15:24:50 -08001633 if (schedulePipModeChangedCallback) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001634 // We need to schedule the PiP mode change after the animation down, so use the
1635 // final bounds
Yunfan Chen279f5582018-12-12 15:24:50 -08001636 mActivityStack.updatePictureInPictureModeForPinnedStackAnimation(
Winson Chungab76bbc2017-08-14 13:33:51 -07001637 mBoundsAnimationTarget, false /* forceUpdate */);
Winson Chung8bca9e42017-04-16 15:59:43 -07001638 }
1639
Tracy Zhouc1f792d2019-05-07 16:32:02 -07001640 if (mAnimationType == BoundsAnimationController.FADE_IN) {
1641 setPinnedStackAlpha(1f);
1642 mActivityStack.mService.notifyPinnedStackAnimationEnded();
Tracy Zhou316b1f52019-06-04 16:05:19 -07001643 return;
Tracy Zhouc1f792d2019-05-07 16:32:02 -07001644 }
1645
wilsonshih4dd07122019-04-03 15:55:02 +08001646 if (finalStackSize != null && !mCancelCurrentBoundsAnimation) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001647 setPinnedStackSize(finalStackSize, null);
Winson Chunge40082ea2018-06-05 16:03:12 -07001648 } else {
1649 // We have been canceled, so the final stack size is null, still run the
1650 // animation-end logic
1651 onPipAnimationEndResize();
Winson Chung8bca9e42017-04-16 15:59:43 -07001652 }
1653
Tracy Zhouc1f792d2019-05-07 16:32:02 -07001654 mActivityStack.mService.notifyPinnedStackAnimationEnded();
1655 if (moveToFullscreen) {
1656 mActivityStack.mService.moveTasksToFullscreenStack(mStackId, true /* onTop */);
Wale Ogunwale480dca02016-02-06 13:58:29 -08001657 }
Winson Chunge40082ea2018-06-05 16:03:12 -07001658 } else {
1659 // No PiP animation, just run the normal animation-end logic
1660 onPipAnimationEndResize();
Wale Ogunwale480dca02016-02-06 13:58:29 -08001661 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001662 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001663
Yunfan Chen279f5582018-12-12 15:24:50 -08001664 /**
1665 * @return the current stack bounds transformed to the given {@param aspectRatio}. If
1666 * the default bounds is {@code null}, then the {@param aspectRatio} is applied to the
1667 * default bounds.
1668 */
1669 Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
1670 if (!mWmService.mSupportsPictureInPicture) {
1671 return null;
1672 }
1673
1674 final DisplayContent displayContent = getDisplayContent();
1675 if (displayContent == null) {
1676 return null;
1677 }
1678
1679 if (!inPinnedWindowingMode()) {
1680 return null;
1681 }
1682
1683 final PinnedStackController pinnedStackController =
1684 displayContent.getPinnedStackController();
1685 if (stackBounds == null) {
1686 // Calculate the aspect ratio bounds from the default bounds
1687 stackBounds = pinnedStackController.getDefaultOrLastSavedBounds();
1688 }
1689
1690 if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
1691 return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
1692 true /* useCurrentMinEdgeSize */);
1693 } else {
1694 return stackBounds;
1695 }
1696 }
1697
1698 /**
1699 * Animates the pinned stack.
1700 */
1701 void animateResizePinnedStack(Rect toBounds, Rect sourceHintBounds,
1702 int animationDuration, boolean fromFullscreen) {
1703 if (!inPinnedWindowingMode()) {
1704 return;
1705 }
1706 // Get the from-bounds
1707 final Rect fromBounds = new Rect();
1708 getBounds(fromBounds);
1709
1710 // Get non-null fullscreen to-bounds for animating if the bounds are null
1711 @SchedulePipModeChangedState int schedulePipModeChangedState =
1712 NO_PIP_MODE_CHANGED_CALLBACKS;
1713 final boolean toFullscreen = toBounds == null;
1714 if (toFullscreen) {
1715 if (fromFullscreen) {
1716 throw new IllegalArgumentException("Should not defer scheduling PiP mode"
1717 + " change on animation to fullscreen.");
1718 }
1719 schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
1720
1721 mWmService.getStackBounds(
1722 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, mTmpToBounds);
1723 if (!mTmpToBounds.isEmpty()) {
1724 // If there is a fullscreen bounds, use that
1725 toBounds = new Rect(mTmpToBounds);
1726 } else {
1727 // Otherwise, use the display bounds
1728 toBounds = new Rect();
1729 getDisplayContent().getBounds(toBounds);
1730 }
1731 } else if (fromFullscreen) {
1732 schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
1733 }
1734
1735 setAnimationFinalBounds(sourceHintBounds, toBounds, toFullscreen);
1736
1737 final Rect finalToBounds = toBounds;
1738 final @SchedulePipModeChangedState int finalSchedulePipModeChangedState =
1739 schedulePipModeChangedState;
1740 final DisplayContent displayContent = getDisplayContent();
Tracy Zhou9c675d42019-04-08 00:32:40 -07001741 @BoundsAnimationController.AnimationType int intendedAnimationType =
1742 displayContent.mBoundsAnimationController.getAnimationType();
1743 if (intendedAnimationType == FADE_IN) {
1744 if (fromFullscreen) {
1745 setPinnedStackAlpha(0f);
1746 }
1747 if (toBounds.width() == fromBounds.width()
1748 && toBounds.height() == fromBounds.height()) {
1749 intendedAnimationType = BoundsAnimationController.BOUNDS;
Hongwei Wangf0b5fb12019-07-25 15:14:47 -07001750 } else if (!fromFullscreen && !toBounds.equals(fromBounds)) {
1751 // intendedAnimationType may have been reset at the end of RecentsAnimation,
1752 // force it to BOUNDS type if we know for certain we're animating to
1753 // a different bounds, especially for expand and collapse of PiP window.
1754 intendedAnimationType = BoundsAnimationController.BOUNDS;
Tracy Zhou9c675d42019-04-08 00:32:40 -07001755 }
1756 }
1757
1758 final @BoundsAnimationController.AnimationType int animationType = intendedAnimationType;
wilsonshih4dd07122019-04-03 15:55:02 +08001759 mCancelCurrentBoundsAnimation = false;
Yunfan Chen279f5582018-12-12 15:24:50 -08001760 displayContent.mBoundsAnimationController.getHandler().post(() -> {
1761 displayContent.mBoundsAnimationController.animateBounds(this, fromBounds,
1762 finalToBounds, animationDuration, finalSchedulePipModeChangedState,
Tracy Zhou9c675d42019-04-08 00:32:40 -07001763 fromFullscreen, toFullscreen, animationType);
Yunfan Chen279f5582018-12-12 15:24:50 -08001764 });
1765 }
1766
1767 /**
1768 * Sets the current picture-in-picture aspect ratio.
1769 */
1770 void setPictureInPictureAspectRatio(float aspectRatio) {
1771 if (!mWmService.mSupportsPictureInPicture) {
1772 return;
1773 }
1774
1775 if (!inPinnedWindowingMode()) {
1776 return;
1777 }
1778
1779 final PinnedStackController pinnedStackController =
1780 getDisplayContent().getPinnedStackController();
1781
1782 if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) == 0) {
1783 return;
1784 }
1785 getAnimationOrCurrentBounds(mTmpFromBounds);
1786 mTmpToBounds.set(mTmpFromBounds);
1787 getPictureInPictureBounds(aspectRatio, mTmpToBounds);
1788 if (!mTmpToBounds.equals(mTmpFromBounds)) {
1789 animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
1790 -1 /* duration */, false /* fromFullscreen */);
1791 }
1792 pinnedStackController.setAspectRatio(
1793 pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)
1794 ? aspectRatio : -1f);
1795 }
1796
1797 /**
1798 * Sets the current picture-in-picture actions.
1799 */
1800 void setPictureInPictureActions(List<RemoteAction> actions) {
1801 if (!mWmService.mSupportsPictureInPicture) {
1802 return;
1803 }
1804
1805 if (!inPinnedWindowingMode()) {
1806 return;
1807 }
1808
1809 getDisplayContent().getPinnedStackController().setActions(actions);
1810 }
1811
Wale Ogunwalef276a6f2018-06-15 08:26:07 -07001812 @Override
1813 public boolean isAttached() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001814 synchronized (mWmService.mGlobalLock) {
Winson Chunga06403d2018-06-28 12:56:53 -07001815 return mDisplayContent != null;
1816 }
Wale Ogunwalef276a6f2018-06-15 08:26:07 -07001817 }
1818
Winson Chung15036ca2018-05-31 15:51:47 -07001819 /**
1820 * Called immediately prior to resizing the tasks at the end of the pinned stack animation.
1821 */
1822 public void onPipAnimationEndResize() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001823 synchronized (mWmService.mGlobalLock) {
Winson Chunga06403d2018-06-28 12:56:53 -07001824 mBoundsAnimating = false;
1825 for (int i = 0; i < mChildren.size(); i++) {
1826 final Task t = mChildren.get(i);
1827 t.clearPreserveNonFloatingState();
1828 }
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001829 mWmService.requestTraversal();
Winson Chung15036ca2018-05-31 15:51:47 -07001830 }
Winson Chung15036ca2018-05-31 15:51:47 -07001831 }
1832
Winson Chung6a38fca2018-03-28 17:57:09 -07001833 @Override
1834 public boolean shouldDeferStartOnMoveToFullscreen() {
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001835 synchronized (mWmService.mGlobalLock) {
Riddle Hsue8b10e32018-11-09 19:35:26 +08001836 if (!isAttached()) {
1837 // Unnecessary to pause the animation because the stack is detached.
1838 return false;
1839 }
1840
Winson Chunga06403d2018-06-28 12:56:53 -07001841 // Workaround for the recents animation -- normally we need to wait for the new activity
1842 // to show before starting the PiP animation, but because we start and show the home
1843 // activity early for the recents animation prior to the PiP animation starting, there
1844 // is no subsequent all-drawn signal. In this case, we can skip the pause when the home
1845 // stack is already visible and drawn.
1846 final TaskStack homeStack = mDisplayContent.getHomeStack();
1847 if (homeStack == null) {
1848 return true;
1849 }
1850 final Task homeTask = homeStack.getTopChild();
1851 if (homeTask == null) {
1852 return true;
1853 }
1854 final AppWindowToken homeApp = homeTask.getTopVisibleAppToken();
1855 if (!homeTask.isVisible() || homeApp == null) {
1856 return true;
1857 }
1858 return !homeApp.allDrawn;
Winson Chung6a38fca2018-03-28 17:57:09 -07001859 }
Winson Chung6a38fca2018-03-28 17:57:09 -07001860 }
1861
Winson Chung8bca9e42017-04-16 15:59:43 -07001862 /**
1863 * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
1864 * bounds and we have a deferred PiP mode changed callback set with the animation.
1865 */
1866 public boolean deferScheduleMultiWindowModeChanged() {
Wale Ogunwale44f036f2017-09-29 05:09:09 -07001867 if (inPinnedWindowingMode()) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001868 return (mBoundsAnimatingRequested || mBoundsAnimating);
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001869 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001870 return false;
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001871 }
1872
Robert Carr8f0a3ad2017-02-15 19:30:28 -08001873 public boolean isForceScaled() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001874 return mBoundsAnimating;
1875 }
1876
Winson Chung40a5f932017-04-13 16:39:36 -07001877 public boolean isAnimatingBounds() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001878 return mBoundsAnimating;
Robert Carr0d00c2e2016-02-29 17:45:02 -08001879 }
Jorim Jaggi6626f542016-08-22 13:08:44 -07001880
Robert Carr18f622f2017-05-08 11:20:43 -07001881 public boolean lastAnimatingBoundsWasToFullscreen() {
1882 return mBoundsAnimatingToFullscreen;
1883 }
1884
Winson Chung40a5f932017-04-13 16:39:36 -07001885 public boolean isAnimatingBoundsToFullscreen() {
Robert Carr18f622f2017-05-08 11:20:43 -07001886 return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
Robert Carr7e4c90e2017-02-15 19:52:38 -08001887 }
1888
Winson Chung8bca9e42017-04-16 15:59:43 -07001889 public boolean pinnedStackResizeDisallowed() {
Winson Chung19953ca2017-04-11 11:19:23 -07001890 if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
1891 return true;
1892 }
1893 return false;
1894 }
1895
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001896 /** Returns true if a removal action is still being deferred. */
1897 boolean checkCompleteDeferredRemoval() {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001898 if (isSelfOrChildAnimating()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001899 return true;
1900 }
Wale Ogunwale10124582016-09-15 20:25:50 -07001901 if (mDeferRemoval) {
1902 removeImmediately();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001903 }
1904
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001905 return super.checkCompleteDeferredRemoval();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001906 }
1907
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001908 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07001909 int getOrientation() {
Wale Ogunwale68278562017-09-23 17:13:55 -07001910 return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
1911 }
1912
1913 private boolean canSpecifyOrientation() {
1914 final int windowingMode = getWindowingMode();
1915 final int activityType = getActivityType();
1916 return windowingMode == WINDOWING_MODE_FULLSCREEN
1917 || activityType == ACTIVITY_TYPE_HOME
1918 || activityType == ACTIVITY_TYPE_RECENTS
1919 || activityType == ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale51362492016-09-08 17:49:17 -07001920 }
Robert Carrf59b8dd2017-10-02 18:58:36 -07001921
chaviw2fb06bc2018-01-19 17:09:15 -08001922 @Override
Robert Carrf59b8dd2017-10-02 18:58:36 -07001923 Dimmer getDimmer() {
1924 return mDimmer;
1925 }
1926
1927 @Override
1928 void prepareSurfaces() {
1929 mDimmer.resetDimStates();
1930 super.prepareSurfaces();
1931 getDimBounds(mTmpDimBoundsRect);
chaviwe07246a2017-12-12 16:18:29 -08001932
1933 // Bounds need to be relative, as the dim layer is a child.
1934 mTmpDimBoundsRect.offsetTo(0, 0);
Robert Carrf59b8dd2017-10-02 18:58:36 -07001935 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) {
1936 scheduleAnimation();
1937 }
1938 }
1939
Tracy Zhou9c675d42019-04-08 00:32:40 -07001940 @Override
1941 public boolean setPinnedStackAlpha(float alpha) {
1942 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
1943 synchronized (mWmService.mGlobalLock) {
Winson Chung8312b1d2019-06-24 11:57:22 -07001944 final SurfaceControl sc = getSurfaceControl();
1945 if (sc == null || !sc.isValid()) {
1946 // If the stack is already removed, don't bother updating any stack animation
1947 return false;
1948 }
1949 getPendingTransaction().setAlpha(sc, mCancelCurrentBoundsAnimation ? 1 : alpha);
Tracy Zhou9c675d42019-04-08 00:32:40 -07001950 scheduleAnimation();
Tracy Zhou316b1f52019-06-04 16:05:19 -07001951 return !mCancelCurrentBoundsAnimation;
Tracy Zhou9c675d42019-04-08 00:32:40 -07001952 }
Tracy Zhou9c675d42019-04-08 00:32:40 -07001953 }
1954
Robert Carrf59b8dd2017-10-02 18:58:36 -07001955 public DisplayInfo getDisplayInfo() {
1956 return mDisplayContent.getDisplayInfo();
1957 }
1958
1959 void dim(float alpha) {
1960 mDimmer.dimAbove(getPendingTransaction(), alpha);
1961 scheduleAnimation();
1962 }
1963
1964 void stopDimming() {
1965 mDimmer.stopDim(getPendingTransaction());
1966 scheduleAnimation();
1967 }
Robert Carr32bcb102018-01-29 15:03:23 -08001968
Jorim Jaggi6de61012018-03-19 14:53:23 +01001969 AnimatingAppWindowTokenRegistry getAnimatingAppWindowTokenRegistry() {
1970 return mAnimatingAppWindowTokenRegistry;
1971 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001972}