blob: 65278837700518030891dcfcfd6352ba6a3919ae [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
Jorim Jaggi2917dc42016-04-11 11:39:13 -070019import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
Chong Zhang73d4b442016-05-25 14:30:36 -070020import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070021import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
22import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwale68278562017-09-23 17:13:55 -070023import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT;
24import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
25import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
26import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale51362492016-09-08 17:49:17 -070027import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070028import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
29import 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;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -070036import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Jorim Jaggiff71d202016-04-14 13:12:36 -070037import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -070038import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070039import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
40import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070041import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
Steven Timotiusaf03df62017-07-18 16:56:43 -070042import static com.android.server.wm.proto.StackProto.ANIMATION_BACKGROUND_SURFACE_IS_DIMMING;
43import static com.android.server.wm.proto.StackProto.BOUNDS;
44import static com.android.server.wm.proto.StackProto.FILLS_PARENT;
45import static com.android.server.wm.proto.StackProto.ID;
46import static com.android.server.wm.proto.StackProto.TASKS;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070047import static com.android.server.wm.proto.StackProto.WINDOW_CONTAINER;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070048
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070049import android.annotation.CallSuper;
Wale Ogunwale60454db2015-01-23 16:05:07 -080050import android.content.res.Configuration;
Craig Mautner05d29032013-05-03 13:40:13 -070051import android.graphics.Rect;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -070052import android.graphics.Region;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080053import android.os.RemoteException;
Craig Mautner2c2549c2013-11-12 08:31:15 -080054import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070055import android.util.Slog;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070056import android.util.SparseArray;
Steven Timotiusaf03df62017-07-18 16:56:43 -070057import android.util.proto.ProtoOutputStream;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070058import android.view.DisplayInfo;
Wale Ogunwale94744212015-09-21 19:01:47 -070059import android.view.Surface;
Filip Gruszczynski54977fe2015-10-19 17:26:45 -070060
Jorim Jaggi737af722015-12-31 10:42:27 +010061import com.android.internal.policy.DividerSnapAlgorithm;
62import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
63import com.android.internal.policy.DockedDividerUtils;
Craig Mautner2c2549c2013-11-12 08:31:15 -080064import com.android.server.EventLogTags;
Craig Mautner05d29032013-05-03 13:40:13 -070065
Craig Mautner00af9fe2013-03-25 09:13:41 -070066import java.io.PrintWriter;
Craig Mautnerc00204b2013-03-05 15:02:14 -080067
Wale Ogunwale14a3fb92016-09-11 15:19:05 -070068public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLayerUser,
Winson Chung8bca9e42017-04-16 15:59:43 -070069 BoundsAnimationTarget {
Chong Zhang198afac2016-04-15 12:03:11 -070070 /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
71 * restrict IME adjustment so that a min portion of top stack remains visible.*/
72 private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
73
74 /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
75 private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070076
Craig Mautner00af9fe2013-03-25 09:13:41 -070077 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080078 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070079
Craig Mautner05d29032013-05-03 13:40:13 -070080 /** The service */
81 private final WindowManagerService mService;
82
Craig Mautner00af9fe2013-03-25 09:13:41 -070083 /** The display this stack sits under. */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -070084 // TODO: Track parent marks like this in WindowContainer.
Craig Mautnerdf88d732014-01-27 09:21:32 -080085 private DisplayContent mDisplayContent;
Craig Mautner00af9fe2013-03-25 09:13:41 -070086
Craig Mautnerb660b9d2014-02-13 10:59:16 -080087 /** For comparison with DisplayContent bounds. */
88 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070089 private Rect mTmpRect2 = new Rect();
Winson Chung19953ca2017-04-11 11:19:23 -070090 private Rect mTmpRect3 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -080091
92 /** Content limits relative to the DisplayContent this sits in. */
93 private Rect mBounds = new Rect();
94
Chong Zhangb816b862016-01-25 12:01:12 -080095 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
96 private final Rect mAdjustedBounds = new Rect();
97
Jorim Jaggieb88d832016-04-13 20:17:43 -070098 /**
99 * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
100 * represent the state when the animation has ended.
101 */
102 private final Rect mFullyAdjustedImeBounds = new Rect();
103
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800104 /** Whether mBounds is fullscreen */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700105 private boolean mFillsParent = true;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800106
Wale Ogunwale94744212015-09-21 19:01:47 -0700107 // Device rotation as of the last time {@link #mBounds} was set.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700108 private int mRotation;
Wale Ogunwale94744212015-09-21 19:01:47 -0700109
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700110 /** Density as of last time {@link #mBounds} was set. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700111 private int mDensity;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700112
Craig Mautner05d29032013-05-03 13:40:13 -0700113 /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700114 private DimLayer mAnimationBackgroundSurface;
Craig Mautner05d29032013-05-03 13:40:13 -0700115
116 /** The particular window with an Animation with non-zero background color. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700117 private WindowStateAnimator mAnimationBackgroundAnimator;
Craig Mautner05d29032013-05-03 13:40:13 -0700118
Craig Mautnerdc548482014-02-05 13:35:24 -0800119 /** Application tokens that are exiting, but still on screen for animations. */
120 final AppTokenList mExitingAppTokens = new AppTokenList();
Wale Ogunwale48458e12017-06-06 10:07:58 -0700121 final AppTokenList mTmpAppTokens = new AppTokenList();
Craig Mautnerdc548482014-02-05 13:35:24 -0800122
Craig Mautner95da1082014-02-24 17:54:35 -0800123 /** Detach this stack from its display when animation completes. */
Wale Ogunwalef6192862016-09-10 13:42:30 -0700124 // TODO: maybe tie this to WindowContainer#removeChild some how...
Wale Ogunwale10124582016-09-15 20:25:50 -0700125 boolean mDeferRemoval;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800126
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800127 private final Rect mTmpAdjustedBounds = new Rect();
128 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700129 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800130 private WindowState mImeWin;
131 private float mMinimizeAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700132 private float mAdjustImeAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700133 private float mAdjustDividerAmount;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800134 private final int mDockedStackMinimizeThickness;
135
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700136 // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
137 // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
138 // would otherwise apply while resizing, while resizing in the bounds animating mode.
Robert Carr1ca6a332016-04-11 18:00:43 -0700139 private boolean mBoundsAnimating = false;
Winson Chung40a5f932017-04-13 16:39:36 -0700140 // Set when an animation has been requested but has not yet started from the UI thread. This is
141 // cleared when the animation actually starts.
142 private boolean mBoundsAnimatingRequested = false;
Robert Carr7e4c90e2017-02-15 19:52:38 -0800143 private boolean mBoundsAnimatingToFullscreen = false;
Winson Chung19953ca2017-04-11 11:19:23 -0700144 private boolean mCancelCurrentBoundsAnimation = false;
Winson Chung84a38342016-11-08 16:15:10 -0800145 private Rect mBoundsAnimationTarget = new Rect();
Winson Chung8bca9e42017-04-16 15:59:43 -0700146 private Rect mBoundsAnimationSourceHintBounds = new Rect();
Robert Carr0d00c2e2016-02-29 17:45:02 -0800147
Chong Zhang167bbfac2016-03-31 09:44:34 -0700148 // Temporary storage for the new bounds that should be used after the configuration change.
149 // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
150 private final Rect mBoundsAfterRotation = new Rect();
151
Robert Carr18f622f2017-05-08 11:20:43 -0700152 Rect mPreAnimationBounds = new Rect();
153
Wale Ogunwale704a3c02017-09-18 15:30:52 -0700154 TaskStack(WindowManagerService service, int stackId, StackWindowController controller) {
Craig Mautner05d29032013-05-03 13:40:13 -0700155 mService = service;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800156 mStackId = stackId;
Wale Ogunwale704a3c02017-09-18 15:30:52 -0700157 setController(controller);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800158 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
159 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700160 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800161 }
162
163 DisplayContent getDisplayContent() {
164 return mDisplayContent;
165 }
166
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700167 Task findHomeTask() {
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700168 if (!isActivityTypeHome() || mChildren.isEmpty()) {
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700169 return null;
170 }
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -0700171 return mChildren.get(mChildren.size() - 1);
Wale Ogunwale15ead902016-09-02 14:30:11 -0700172 }
173
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700174 /**
175 * Set the bounds of the stack and its containing tasks.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700176 * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700177 * @param configs Configuration for individual tasks, keyed by task id.
178 * @param taskBounds Bounds for individual tasks, keyed by task id.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700179 * @return True if the stack bounds was changed.
180 * */
Wale Ogunwalea6e902e2015-09-21 18:37:15 -0700181 boolean setBounds(
Jorim Jaggidc249c42015-12-15 14:57:31 -0800182 Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
183 SparseArray<Rect> taskTempInsetBounds) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500184 setBounds(stackBounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700185
186 // Update bounds of containing tasks.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700187 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
188 final Task task = mChildren.get(taskNdx);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700189 Configuration config = configs.get(task.mTaskId);
190 if (config != null) {
191 Rect bounds = taskBounds.get(task.mTaskId);
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700192 task.resizeLocked(bounds, config, false /* forced */);
193 task.setTempInsetBounds(taskTempInsetBounds != null ?
194 taskTempInsetBounds.get(task.mTaskId) : null);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700195 } else {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800196 Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700197 }
198 }
199 return true;
200 }
201
Jorim Jaggi0429f352015-12-22 16:29:16 +0100202 void prepareFreezingTaskBounds() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700203 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
204 final Task task = mChildren.get(taskNdx);
Jorim Jaggi0429f352015-12-22 16:29:16 +0100205 task.prepareFreezingBounds();
206 }
207 }
208
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800209 /**
210 * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
211 * the normal task bounds.
212 *
213 * @param bounds The adjusted bounds.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800214 */
Jorim Jaggieb88d832016-04-13 20:17:43 -0700215 private void setAdjustedBounds(Rect bounds) {
216 if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
217 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800218 }
219
220 mAdjustedBounds.set(bounds);
221 final boolean adjusted = !mAdjustedBounds.isEmpty();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700222 Rect insetBounds = null;
Matthew Nge15352e2016-12-20 15:36:29 -0800223 if (adjusted && isAdjustedForMinimizedDockedStack()) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700224 insetBounds = mBounds;
Chong Zhang5117e272016-05-03 12:47:34 -0700225 } else if (adjusted && mAdjustedForIme) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700226 if (mImeGoingAway) {
227 insetBounds = mBounds;
228 } else {
229 insetBounds = mFullyAdjustedImeBounds;
230 }
231 }
Chong Zhang741c0ba2016-05-27 12:52:11 -0700232 alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700233 mDisplayContent.setLayoutNeeded();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800234 }
235
236 private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700237 if (mFillsParent) {
Chong Zhangb816b862016-01-25 12:01:12 -0800238 return;
239 }
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700240
241 final boolean alignBottom = mAdjustedForIme && getDockSide() == DOCKED_TOP;
242
Chong Zhangb816b862016-01-25 12:01:12 -0800243 // Update bounds of containing tasks.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700244 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
245 final Task task = mChildren.get(taskNdx);
Chong Zhang2e2c81a2016-07-15 11:28:17 -0700246 task.alignToAdjustedBounds(adjustedBounds, tempInsetBounds, alignBottom);
Chong Zhangb816b862016-01-25 12:01:12 -0800247 }
248 }
249
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700250 private boolean setBounds(Rect bounds) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700251 boolean oldFullscreen = mFillsParent;
Wale Ogunwale94744212015-09-21 19:01:47 -0700252 int rotation = Surface.ROTATION_0;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700253 int density = DENSITY_DPI_UNDEFINED;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800254 if (mDisplayContent != null) {
255 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwale94744212015-09-21 19:01:47 -0700256 rotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700257 density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700258 mFillsParent = bounds == null;
259 if (mFillsParent) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800260 bounds = mTmpRect;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800261 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800262 }
263
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800264 if (bounds == null) {
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800265 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800266 return false;
267 }
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700268 if (mBounds.equals(bounds) && oldFullscreen == mFillsParent && mRotation == rotation) {
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800269 return false;
270 }
271
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700272 if (mDisplayContent != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800273 mDisplayContent.mDimLayerController.updateDimLayer(this);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700274 mAnimationBackgroundSurface.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700275 }
276
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800277 mBounds.set(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700278 mRotation = rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700279 mDensity = density;
Chong Zhangb816b862016-01-25 12:01:12 -0800280
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800281 updateAdjustedBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800282
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800283 return true;
284 }
285
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700286 /** Bounds of the stack without adjusting for other factors in the system like visibility
287 * of docked stack.
288 * Most callers should be using {@link #getBounds} as it take into consideration other system
289 * factors. */
290 void getRawBounds(Rect out) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800291 out.set(mBounds);
292 }
293
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700294 /** Return true if the current bound can get outputted to the rest of the system as-is. */
295 private boolean useCurrentBounds() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700296 if (mFillsParent
Wale Ogunwale926aade2017-08-29 11:24:37 -0700297 || !inSplitScreenSecondaryWindowingMode()
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700298 || mDisplayContent == null
299 || mDisplayContent.getDockedStackLocked() != null) {
300 return true;
301 }
302 return false;
303 }
304
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700305 public void getBounds(Rect out) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700306 if (useCurrentBounds()) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -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
310 // system.
311 if (!mAdjustedBounds.isEmpty()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800312 out.set(mAdjustedBounds);
313 } else {
314 out.set(mBounds);
315 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700316 return;
317 }
318
319 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
320 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
321 // system.
322 mDisplayContent.getLogicalDisplayRect(out);
323 }
324
Winson Chung84a38342016-11-08 16:15:10 -0800325 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700326 * Sets the bounds animation target bounds ahead of an animation. This can't currently be done
327 * in onAnimationStart() since that is started on the UiThread.
Winson Chung84a38342016-11-08 16:15:10 -0800328 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700329 void setAnimationFinalBounds(Rect sourceHintBounds, Rect destBounds, boolean toFullscreen) {
Winson Chung40a5f932017-04-13 16:39:36 -0700330 mBoundsAnimatingRequested = true;
Winson Chung8bca9e42017-04-16 15:59:43 -0700331 mBoundsAnimatingToFullscreen = toFullscreen;
Winson Chung08f81892017-03-02 15:40:51 -0800332 if (destBounds != null) {
333 mBoundsAnimationTarget.set(destBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800334 } else {
335 mBoundsAnimationTarget.setEmpty();
336 }
Winson Chung8bca9e42017-04-16 15:59:43 -0700337 if (sourceHintBounds != null) {
338 mBoundsAnimationSourceHintBounds.set(sourceHintBounds);
339 } else {
340 mBoundsAnimationSourceHintBounds.setEmpty();
341 }
Robert Carr18f622f2017-05-08 11:20:43 -0700342
343 mPreAnimationBounds.set(mBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800344 }
345
346 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700347 * @return the final bounds for the bounds animation.
Winson Chung08f81892017-03-02 15:40:51 -0800348 */
Winson Chung40a5f932017-04-13 16:39:36 -0700349 void getFinalAnimationBounds(Rect outBounds) {
350 outBounds.set(mBoundsAnimationTarget);
Winson Chung08f81892017-03-02 15:40:51 -0800351 }
352
353 /**
Winson Chung40a5f932017-04-13 16:39:36 -0700354 * @return the final source bounds for the bounds animation.
Winson Chung84a38342016-11-08 16:15:10 -0800355 */
Winson Chung8bca9e42017-04-16 15:59:43 -0700356 void getFinalAnimationSourceHintBounds(Rect outBounds) {
357 outBounds.set(mBoundsAnimationSourceHintBounds);
Winson Chung40a5f932017-04-13 16:39:36 -0700358 }
359
360 /**
361 * @return the final animation bounds if the task stack is currently being animated, or the
362 * current stack bounds otherwise.
363 */
364 void getAnimationOrCurrentBounds(Rect outBounds) {
365 if ((mBoundsAnimatingRequested || mBoundsAnimating) && !mBoundsAnimationTarget.isEmpty()) {
366 getFinalAnimationBounds(outBounds);
Winson Chung84a38342016-11-08 16:15:10 -0800367 return;
368 }
369 getBounds(outBounds);
370 }
371
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800372 /** Bounds of the stack with other system factors taken into consideration. */
373 @Override
374 public void getDimBounds(Rect out) {
375 getBounds(out);
376 }
377
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700378 void updateDisplayInfo(Rect bounds) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800379 if (mDisplayContent == null) {
380 return;
381 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100382
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700383 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
384 mChildren.get(taskNdx).updateDisplayInfo(mDisplayContent);
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800385 }
386 if (bounds != null) {
387 setBounds(bounds);
388 return;
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700389 } else if (mFillsParent) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800390 setBounds(null);
391 return;
392 }
393
394 mTmpRect2.set(mBounds);
395 final int newRotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700396 final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
397 if (mRotation == newRotation && mDensity == newDensity) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800398 setBounds(mTmpRect2);
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800399 }
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700400
401 // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800402 }
403
Andrii Kulian441e4492016-09-29 15:25:00 -0700404 /** @return true if bounds were updated to some non-empty value. */
405 boolean updateBoundsAfterConfigChange() {
Andrii Kulian0be2cfe2016-05-25 14:27:39 -0700406 if (mDisplayContent == null) {
407 // If the stack is already detached we're not updating anything,
408 // as it's going away soon anyway.
409 return false;
410 }
Winson Chung19953ca2017-04-11 11:19:23 -0700411
412 if (mStackId == PINNED_STACK_ID) {
Winson Chung40a5f932017-04-13 16:39:36 -0700413 getAnimationOrCurrentBounds(mTmpRect2);
Winson Chung19953ca2017-04-11 11:19:23 -0700414 boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
415 mTmpRect2, mTmpRect3);
416 if (updated) {
417 mBoundsAfterRotation.set(mTmpRect3);
418
419 // Once we've set the bounds based on the rotation of the old bounds in the new
420 // orientation, clear the animation target bounds since they are obsolete, and
421 // cancel any currently running animations
422 mBoundsAnimationTarget.setEmpty();
Winson Chung8bca9e42017-04-16 15:59:43 -0700423 mBoundsAnimationSourceHintBounds.setEmpty();
Winson Chung19953ca2017-04-11 11:19:23 -0700424 mCancelCurrentBoundsAnimation = true;
425 return true;
426 }
427 }
428
Jorim Jaggi737af722015-12-31 10:42:27 +0100429 final int newRotation = getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700430 final int newDensity = getDisplayInfo().logicalDensityDpi;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800431
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700432 if (mRotation == newRotation && mDensity == newDensity) {
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700433 // Nothing to do here as we already update the state in updateDisplayInfo.
Chong Zhang167bbfac2016-03-31 09:44:34 -0700434 return false;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800435 }
436
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700437 if (mFillsParent) {
Chong Zhangccc335c2016-05-13 11:04:38 -0700438 // Update stack bounds again since rotation changed since updateDisplayInfo().
439 setBounds(null);
440 // Return false since we don't need the client to resize.
441 return false;
442 }
443
Wale Ogunwale5952f9a2016-04-25 13:40:30 -0700444 mTmpRect2.set(mBounds);
Jorim Jaggi737af722015-12-31 10:42:27 +0100445 mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Winson Chungcd1ff642016-10-26 09:44:43 -0700446 switch (mStackId) {
Winson Chungcd1ff642016-10-26 09:44:43 -0700447 case DOCKED_STACK_ID:
448 repositionDockedStackAfterRotation(mTmpRect2);
449 snapDockedStackAfterRotation(mTmpRect2);
450 final int newDockSide = getDockSide(mTmpRect2);
451
452 // Update the dock create mode and clear the dock create bounds, these
453 // might change after a rotation and the original values will be invalid.
454 mService.setDockedStackCreateStateLocked(
455 (newDockSide == DOCKED_LEFT || newDockSide == DOCKED_TOP)
456 ? DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT
457 : DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT,
458 null);
459 mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
460 break;
Jorim Jaggi737af722015-12-31 10:42:27 +0100461 }
462
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700463 mBoundsAfterRotation.set(mTmpRect2);
Chong Zhang167bbfac2016-03-31 09:44:34 -0700464 return true;
465 }
466
Matthew Ngaa2b6202017-02-10 14:48:21 -0800467 void getBoundsForNewConfiguration(Rect outBounds) {
Chong Zhang167bbfac2016-03-31 09:44:34 -0700468 outBounds.set(mBoundsAfterRotation);
469 mBoundsAfterRotation.setEmpty();
Jorim Jaggi737af722015-12-31 10:42:27 +0100470 }
471
472 /**
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800473 * Some dock sides are not allowed by the policy. This method queries the policy and moves
474 * the docked stack around if needed.
475 *
476 * @param inOutBounds the bounds of the docked stack to adjust
477 */
478 private void repositionDockedStackAfterRotation(Rect inOutBounds) {
479 int dockSide = getDockSide(inOutBounds);
480 if (mService.mPolicy.isDockSideAllowed(dockSide)) {
481 return;
482 }
483 mDisplayContent.getLogicalDisplayRect(mTmpRect);
484 dockSide = DockedDividerUtils.invertDockSide(dockSide);
485 switch (dockSide) {
486 case DOCKED_LEFT:
487 int movement = inOutBounds.left;
488 inOutBounds.left -= movement;
489 inOutBounds.right -= movement;
490 break;
491 case DOCKED_RIGHT:
492 movement = mTmpRect.right - inOutBounds.right;
493 inOutBounds.left += movement;
494 inOutBounds.right += movement;
495 break;
496 case DOCKED_TOP:
497 movement = inOutBounds.top;
498 inOutBounds.top -= movement;
499 inOutBounds.bottom -= movement;
500 break;
501 case DOCKED_BOTTOM:
502 movement = mTmpRect.bottom - inOutBounds.bottom;
503 inOutBounds.top += movement;
504 inOutBounds.bottom += movement;
505 break;
506 }
507 }
508
509 /**
Jorim Jaggi737af722015-12-31 10:42:27 +0100510 * Snaps the bounds after rotation to the closest snap target for the docked stack.
511 */
512 private void snapDockedStackAfterRotation(Rect outBounds) {
513
514 // Calculate the current position.
515 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
Andrii Kulian5406e7a2016-10-21 11:55:23 -0700516 final int dividerSize = mDisplayContent.getDockedDividerController().getContentWidth();
Jorim Jaggi737af722015-12-31 10:42:27 +0100517 final int dockSide = getDockSide(outBounds);
518 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
519 dockSide, dividerSize);
520 final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
521 final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
522
523 // Snap the position to a target.
524 final int rotation = displayInfo.rotation;
Andrii Kulian441e4492016-09-29 15:25:00 -0700525 final int orientation = mDisplayContent.getConfiguration().orientation;
Jorim Jaggi737af722015-12-31 10:42:27 +0100526 mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
527 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Jorim Jaggidf012d52016-01-15 22:40:13 -0800528 mService.mContext.getResources(), displayWidth, displayHeight,
Matthew Nge15352e2016-12-20 15:36:29 -0800529 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds,
530 isMinimizedDockAndHomeStackResizable());
Jorim Jaggi737af722015-12-31 10:42:27 +0100531 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
532
533 // Recalculate the bounds based on the position of the target.
534 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
535 outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
536 dividerSize);
537 }
538
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700539 // 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 -0800540 void addTask(Task task, int position) {
541 addTask(task, position, task.showForAllUsers(), true /* moveParents */);
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700542 }
543
Craig Mautner00af9fe2013-03-25 09:13:41 -0700544 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800545 * Put a Task in this stack. Used for adding only.
546 * When task is added to top of the stack, the entire branch of the hierarchy (including stack
547 * and display) will be brought to top.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700548 * @param task The task to add.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800549 * @param position Target position to add the task to.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700550 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700551 */
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800552 void addTask(Task task, int position, boolean showForAllUsers, boolean moveParents) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800553 final TaskStack currentStack = task.mStack;
554 // TODO: We pass stack to task's constructor, but we still need to call this method.
555 // This doesn't make sense, mStack will already be set equal to "this" at this point.
556 if (currentStack != null && currentStack.mStackId != mStackId) {
557 throw new IllegalStateException("Trying to add taskId=" + task.mTaskId
558 + " to stackId=" + mStackId
559 + ", but it is already attached to stackId=" + task.mStack.mStackId);
560 }
561
Andrii Kuliand2765632016-12-12 22:26:34 -0800562 // Add child task.
563 task.mStack = this;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800564 addChild(task, null);
Andrii Kuliand2765632016-12-12 22:26:34 -0800565
566 // Move child to a proper position, as some restriction for position might apply.
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800567 positionChildAt(position, task, moveParents /* includingParents */, showForAllUsers);
Andrii Kuliand2765632016-12-12 22:26:34 -0800568 }
569
570 @Override
571 void positionChildAt(int position, Task child, boolean includingParents) {
572 positionChildAt(position, child, includingParents, child.showForAllUsers());
573 }
574
575 /**
576 * Overridden version of {@link TaskStack#positionChildAt(int, Task, boolean)}. Used in
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800577 * {@link TaskStack#addTask(Task, int, boolean showForAllUsers, boolean)}, as it can receive
Andrii Kuliand2765632016-12-12 22:26:34 -0800578 * showForAllUsers param from {@link AppWindowToken} instead of {@link Task#showForAllUsers()}.
579 */
580 private void positionChildAt(int position, Task child, boolean includingParents,
581 boolean showForAllUsers) {
582 final int targetPosition = findPositionForTask(child, position, showForAllUsers,
583 false /* addingNew */);
584 super.positionChildAt(targetPosition, child, includingParents);
585
586 // Log positioning.
587 if (DEBUG_TASK_MOVEMENT)
588 Slog.d(TAG_WM, "positionTask: task=" + this + " position=" + position);
589
590 final int toTop = targetPosition == mChildren.size() - 1 ? 1 : 0;
591 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, child.mTaskId, toTop, targetPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700592 }
593
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700594 // 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 -0800595 // have to do complicated things like we are doing in this method.
596 private int findPositionForTask(Task task, int targetPosition, boolean showForAllUsers,
597 boolean addingNew) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700598 final boolean canShowTask =
599 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
Andrii Kuliand2765632016-12-12 22:26:34 -0800600
601 final int stackSize = mChildren.size();
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700602 int minPosition = 0;
Andrii Kuliand2765632016-12-12 22:26:34 -0800603 int maxPosition = addingNew ? stackSize : stackSize - 1;
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700604
605 if (canShowTask) {
606 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700607 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700608 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700609 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700610 // Reset position based on minimum/maximum possible positions.
Andrii Kuliand2765632016-12-12 22:26:34 -0800611 return Math.min(Math.max(targetPosition, minPosition), maxPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700612 }
613
614 /** Calculate the minimum possible position for a task that can be shown to the user.
615 * The minimum position will be above all other tasks that can't be shown.
616 * @param minPosition The minimum position the caller is suggesting.
617 * We will start adjusting up from here.
618 * @param size The size of the current task list.
619 */
620 private int computeMinPosition(int minPosition, int size) {
621 while (minPosition < size) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700622 final Task tmpTask = mChildren.get(minPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700623 final boolean canShowTmpTask =
624 tmpTask.showForAllUsers()
625 || mService.isCurrentProfileLocked(tmpTask.mUserId);
626 if (canShowTmpTask) {
627 break;
628 }
629 minPosition++;
630 }
631 return minPosition;
632 }
633
634 /** Calculate the maximum possible position for a task that can't be shown to the user.
635 * The maximum position will be below all other tasks that can be shown.
636 * @param maxPosition The maximum position the caller is suggesting.
637 * We will start adjusting down from here.
638 */
639 private int computeMaxPosition(int maxPosition) {
640 while (maxPosition > 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800641 final Task tmpTask = mChildren.get(maxPosition);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700642 final boolean canShowTmpTask =
643 tmpTask.showForAllUsers()
644 || mService.isCurrentProfileLocked(tmpTask.mUserId);
645 if (!canShowTmpTask) {
646 break;
647 }
648 maxPosition--;
649 }
650 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800651 }
652
Craig Mautner00af9fe2013-03-25 09:13:41 -0700653 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800654 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
655 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700656 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700657 */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700658 @Override
659 void removeChild(Task task) {
660 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeChild: task=" + task);
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700661
662 super.removeChild(task);
Andrii Kuliand2765632016-12-12 22:26:34 -0800663 task.mStack = null;
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700664
Craig Mautnerdf88d732014-01-27 09:21:32 -0800665 if (mDisplayContent != null) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700666 if (mChildren.isEmpty()) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800667 getParent().positionChildAt(POSITION_BOTTOM, this, false /* includingParents */);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800668 }
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -0700669 mDisplayContent.setLayoutNeeded();
Craig Mautner04a0ea62014-01-13 12:51:26 -0800670 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800671 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
672 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Bryce Lee6d410262017-02-28 15:30:17 -0800673 if (wtoken.getTask() == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800674 wtoken.mIsExiting = false;
675 mExitingAppTokens.remove(appNdx);
676 }
677 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800678 }
679
Wale Ogunwale02319a62016-09-26 15:21:22 -0700680 void onDisplayChanged(DisplayContent dc) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800681 if (mDisplayContent != null) {
Wale Ogunwale02319a62016-09-26 15:21:22 -0700682 throw new IllegalStateException("onDisplayChanged: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800683 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800684
Wale Ogunwale02319a62016-09-26 15:21:22 -0700685 mDisplayContent = dc;
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100686 mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
687 "animation background stackId=" + mStackId);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700688
689 Rect bounds = null;
Wale Ogunwale1666e312016-12-16 11:27:18 -0800690 final TaskStack dockedStack = dc.getDockedStackIgnoringVisibility();
Wale Ogunwale3797c222015-10-27 14:21:58 -0700691 if (mStackId == DOCKED_STACK_ID
Wale Ogunwale926aade2017-08-29 11:24:37 -0700692 || (dockedStack != null && inSplitScreenSecondaryWindowingMode()
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700693 && !dockedStack.fillsParent())) {
Wale Ogunwale3797c222015-10-27 14:21:58 -0700694 // The existence of a docked stack affects the size of other static stack created since
Jorim Jaggi65002e12016-04-21 18:25:49 -0700695 // the docked stack occupies a dedicated region on screen, but only if the dock stack is
696 // not fullscreen. If it's fullscreen, it means that we are in the transition of
697 // dismissing it, so we must not resize this stack.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700698 bounds = new Rect();
Wale Ogunwale02319a62016-09-26 15:21:22 -0700699 dc.getLogicalDisplayRect(mTmpRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700700 mTmpRect2.setEmpty();
701 if (dockedStack != null) {
702 dockedStack.getRawBounds(mTmpRect2);
703 }
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800704 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700705 == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
706 getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100707 mDisplayContent.mDividerControllerLocked.getContentWidth(),
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700708 dockedOnTopOrLeft);
Winson Chung19953ca2017-04-11 11:19:23 -0700709 } else if (mStackId == PINNED_STACK_ID) {
710 // Update the bounds based on any changes to the display info
Winson Chung40a5f932017-04-13 16:39:36 -0700711 getAnimationOrCurrentBounds(mTmpRect2);
Winson Chung19953ca2017-04-11 11:19:23 -0700712 boolean updated = mDisplayContent.mPinnedStackControllerLocked.onTaskStackBoundsChanged(
713 mTmpRect2, mTmpRect3);
714 if (updated) {
715 bounds = new Rect(mTmpRect3);
716 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700717 }
718
719 updateDisplayInfo(bounds);
Wale Ogunwale02319a62016-09-26 15:21:22 -0700720 super.onDisplayChanged(dc);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700721 }
722
Matthew Ngaa2b6202017-02-10 14:48:21 -0800723 /**
724 * Determines the stack and task bounds of the other stack when in docked mode. The current task
725 * bounds is passed in but depending on the stack, the task and stack must match. Only in
726 * minimized mode with resizable launcher, the other stack ignores calculating the stack bounds
727 * and uses the task bounds passed in as the stack and task bounds, otherwise the stack bounds
728 * is calculated and is also used for its task bounds.
729 * If any of the out bounds are empty, it represents default bounds
730 *
731 * @param currentTempTaskBounds the current task bounds of the other stack
732 * @param outStackBounds the calculated stack bounds of the other stack
733 * @param outTempTaskBounds the calculated task bounds of the other stack
734 * @param ignoreVisibility ignore visibility in getting the stack bounds
735 */
736 void getStackDockedModeBoundsLocked(Rect currentTempTaskBounds, Rect outStackBounds,
737 Rect outTempTaskBounds, boolean ignoreVisibility) {
738 outTempTaskBounds.setEmpty();
739
740 // When the home stack is resizable, should always have the same stack and task bounds
Wale Ogunwale68278562017-09-23 17:13:55 -0700741 if (isActivityTypeHome()) {
Winson Chungf7fb5e32017-05-23 17:47:05 -0700742 final Task homeTask = findHomeTask();
743 if (homeTask != null && homeTask.isResizeable()) {
Wale Ogunwale649c1602017-04-24 10:15:31 -0700744 // Calculate the home stack bounds when in docked mode and the home stack is
745 // resizeable.
746 getDisplayContent().mDividerControllerLocked
747 .getHomeStackBoundsInDockedMode(outStackBounds);
748 } else {
749 // Home stack isn't resizeable, so don't specify stack bounds.
750 outStackBounds.setEmpty();
751 }
752
Matthew Ngaa2b6202017-02-10 14:48:21 -0800753 outTempTaskBounds.set(outStackBounds);
754 return;
755 }
756
757 // When minimized state, the stack bounds for all non-home and docked stack bounds should
758 // match the passed task bounds
759 if (isMinimizedDockAndHomeStackResizable() && currentTempTaskBounds != null) {
760 outStackBounds.set(currentTempTaskBounds);
761 return;
Matthew Nge15352e2016-12-20 15:36:29 -0800762 }
763
Wale Ogunwale926aade2017-08-29 11:24:37 -0700764 if (!inSplitScreenWindowingMode() || mDisplayContent == null) {
Matthew Ngaa2b6202017-02-10 14:48:21 -0800765 outStackBounds.set(mBounds);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700766 return;
767 }
768
Wale Ogunwale1666e312016-12-16 11:27:18 -0800769 final TaskStack dockedStack = mDisplayContent.getDockedStackIgnoringVisibility();
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700770 if (dockedStack == null) {
771 // Not sure why you are calling this method when there is no docked stack...
772 throw new IllegalStateException(
773 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
774 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700775 if (!ignoreVisibility && !dockedStack.isVisible()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700776 // The docked stack is being dismissed, but we caught before it finished being
777 // dismissed. In that case we want to treat it as if it is not occupying any space and
778 // let others occupy the whole display.
Matthew Ngaa2b6202017-02-10 14:48:21 -0800779 mDisplayContent.getLogicalDisplayRect(outStackBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700780 return;
781 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700782
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700783 final int dockedSide = dockedStack.getDockSide();
784 if (dockedSide == DOCKED_INVALID) {
785 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800786 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Matthew Ngaa2b6202017-02-10 14:48:21 -0800787 outStackBounds.set(mBounds);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700788 return;
789 }
790
791 mDisplayContent.getLogicalDisplayRect(mTmpRect);
792 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800793 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Matthew Ngaa2b6202017-02-10 14:48:21 -0800794 getStackDockedModeBounds(mTmpRect, outStackBounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100795 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700796
797 }
798
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700799 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700800 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700801 * @param displayRect The bounds of the display the docked stack is on.
802 * @param outBounds Output bounds that should be used for the stack.
803 * @param stackId Id of stack we are calculating the bounds for.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700804 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700805 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
806 * close to the side of the dock.
807 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700808 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800809 private void getStackDockedModeBounds(
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700810 Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
811 boolean dockOnTopOrLeft) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700812 final boolean dockedStack = stackId == DOCKED_STACK_ID;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700813 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700814
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700815 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700816 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800817 if (mService.mDockedStackCreateBounds != null) {
818 outBounds.set(mService.mDockedStackCreateBounds);
819 return;
820 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100821
822 // The initial bounds of the docked stack when it is created about half the screen space
823 // and its bounds can be adjusted after that. The bounds of all other stacks are
824 // adjusted to occupy whatever screen space the docked stack isn't occupying.
825 final DisplayInfo di = mDisplayContent.getDisplayInfo();
826 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
827 mTmpRect2);
828 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100829 di.logicalWidth,
830 di.logicalHeight,
831 dockDividerWidth,
Andrii Kulian441e4492016-09-29 15:25:00 -0700832 mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT,
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100833 mTmpRect2).getMiddleTarget().position;
834
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700835 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700836 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100837 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700838 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100839 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700840 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700841 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700842 if (splitHorizontally) {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700843 outBounds.left = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700844 } else {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700845 outBounds.top = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700846 }
847 }
848 return;
849 }
850
851 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700852 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700853 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700854 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700855 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700856 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700857 }
858 } else {
859 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700860 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700861 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700862 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700863 }
864 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800865 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700866 }
867
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800868 void resetDockedStackToMiddle() {
869 if (mStackId != DOCKED_STACK_ID) {
870 throw new IllegalStateException("Not a docked stack=" + this);
871 }
872
873 mService.mDockedStackCreateBounds = null;
874
875 final Rect bounds = new Rect();
Matthew Nge15352e2016-12-20 15:36:29 -0800876 final Rect tempBounds = new Rect();
Matthew Ngaa2b6202017-02-10 14:48:21 -0800877 getStackDockedModeBoundsLocked(null /* currentTempTaskBounds */, bounds, tempBounds,
878 true /*ignoreVisibility*/);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800879 getController().requestResize(bounds);
880 }
881
882 @Override
883 StackWindowController getController() {
884 return (StackWindowController) super.getController();
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800885 }
886
Wale Ogunwale10124582016-09-15 20:25:50 -0700887 @Override
888 void removeIfPossible() {
889 if (isAnimating()) {
890 mDeferRemoval = true;
891 return;
892 }
893 removeImmediately();
894 }
895
896 @Override
897 void removeImmediately() {
898 super.removeImmediately();
899
Andrii Kulian839def92016-11-02 10:58:58 -0700900 onRemovedFromDisplay();
901 }
902
903 /**
904 * Removes the stack it from its current parent, so it can be either destroyed completely or
905 * re-parented.
906 */
907 void onRemovedFromDisplay() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700908 mDisplayContent.mDimLayerController.removeDimLayerUser(this);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800909 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -0700910
911 if (mAnimationBackgroundSurface != null) {
912 mAnimationBackgroundSurface.destroySurface();
913 mAnimationBackgroundSurface = null;
914 }
Wale Ogunwale10124582016-09-15 20:25:50 -0700915
916 if (mStackId == DOCKED_STACK_ID) {
Andrii Kulian839def92016-11-02 10:58:58 -0700917 mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false);
Wale Ogunwale10124582016-09-15 20:25:50 -0700918 }
Andrii Kulian839def92016-11-02 10:58:58 -0700919
920 mDisplayContent = null;
921 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700922 }
923
Craig Mautner05d29032013-05-03 13:40:13 -0700924 void resetAnimationBackgroundAnimator() {
925 mAnimationBackgroundAnimator = null;
Erik Wolsheimer0e7f7b32017-09-29 12:12:47 -0700926 if (mAnimationBackgroundSurface != null) {
927 mAnimationBackgroundSurface.hide();
928 }
Craig Mautner05d29032013-05-03 13:40:13 -0700929 }
930
Craig Mautner05d29032013-05-03 13:40:13 -0700931 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
932 int animLayer = winAnimator.mAnimLayer;
933 if (mAnimationBackgroundAnimator == null
934 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
935 mAnimationBackgroundAnimator = winAnimator;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -0700936 animLayer = mDisplayContent.getLayerForAnimationBackground(winAnimator);
937 mAnimationBackgroundSurface.show(animLayer - LAYER_OFFSET_DIM,
Craig Mautner05d29032013-05-03 13:40:13 -0700938 ((color >> 24) & 0xff) / 255f, 0);
939 }
940 }
941
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700942 // TODO: Should each user have there own stacks?
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000943 @Override
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800944 void switchUser() {
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000945 super.switchUser();
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700946 int top = mChildren.size();
Craig Mautnerac6f8432013-07-17 13:24:59 -0700947 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700948 Task task = mChildren.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700949 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700950 mChildren.remove(taskNdx);
951 mChildren.add(task);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700952 --top;
953 }
954 }
955 }
956
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800957 /**
958 * Adjusts the stack bounds if the IME is visible.
959 *
960 * @param imeWin The IME window.
961 */
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700962 void setAdjustedForIme(WindowState imeWin, boolean forceUpdate) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800963 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -0700964 mImeGoingAway = false;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700965 if (!mAdjustedForIme || forceUpdate) {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700966 mAdjustedForIme = true;
967 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -0700968 mAdjustDividerAmount = 0f;
969 updateAdjustForIme(0f, 0f, true /* force */);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700970 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700971 }
972
973 boolean isAdjustedForIme() {
Chong Zhang5117e272016-05-03 12:47:34 -0700974 return mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700975 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700976
977 boolean isAnimatingForIme() {
978 return mImeWin != null && mImeWin.isAnimatingLw();
979 }
980
981 /**
982 * Update the stack's bounds (crop or position) according to the IME window's
983 * current position. When IME window is animated, the bottom stack is animated
984 * together to track the IME window's current position, and the top stack is
985 * cropped as necessary.
986 *
987 * @return true if a traversal should be performed after the adjustment.
988 */
Chong Zhangf347ab52016-04-18 21:02:01 -0700989 boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
990 if (adjustAmount != mAdjustImeAmount
991 || adjustDividerAmount != mAdjustDividerAmount || force) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700992 mAdjustImeAmount = adjustAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700993 mAdjustDividerAmount = adjustDividerAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700994 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +0200995 return isVisible();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700996 } else {
997 return false;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700998 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800999 }
1000
1001 /**
1002 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -07001003 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
1004 * animations; otherwise, set flag and animates the window away together
1005 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001006 */
Chong Zhangbaba7832016-03-24 10:21:26 -07001007 void resetAdjustedForIme(boolean adjustBoundsNow) {
1008 if (adjustBoundsNow) {
1009 mImeWin = null;
1010 mAdjustedForIme = false;
1011 mImeGoingAway = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -07001012 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -07001013 mAdjustDividerAmount = 0f;
Chong Zhangbaba7832016-03-24 10:21:26 -07001014 updateAdjustedBounds();
Wale Ogunwale68278562017-09-23 17:13:55 -07001015 mService.setResizeDimLayer(false, getWindowingMode(), 1.0f);
Chong Zhangbaba7832016-03-24 10:21:26 -07001016 } else {
1017 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001018 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001019 }
1020
1021 /**
1022 * Sets the amount how much we currently minimize our stack.
1023 *
1024 * @param minimizeAmount The amount, between 0 and 1.
1025 * @return Whether the amount has changed and a layout is needed.
1026 */
1027 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
1028 if (minimizeAmount != mMinimizeAmount) {
1029 mMinimizeAmount = minimizeAmount;
1030 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +02001031 return isVisible();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001032 } else {
1033 return false;
1034 }
1035 }
1036
Matthew Nge15352e2016-12-20 15:36:29 -08001037 boolean shouldIgnoreInput() {
1038 return isAdjustedForMinimizedDockedStack() || mStackId == DOCKED_STACK_ID &&
1039 isMinimizedDockAndHomeStackResizable();
Jorim Jaggi409635b2016-04-01 15:32:28 -07001040 }
1041
Jorim Jaggiff71d202016-04-14 13:12:36 -07001042 /**
1043 * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
1044 * to the list of to be drawn windows the service is waiting for.
1045 */
1046 void beginImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001047 for (int j = mChildren.size() - 1; j >= 0; j--) {
1048 final Task task = mChildren.get(j);
Wale Ogunwale44f21802016-09-02 12:49:48 -07001049 if (task.hasContentToDisplay()) {
Jorim Jaggiff71d202016-04-14 13:12:36 -07001050 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001051 task.setWaitingForDrawnIfResizingChanged();
Jorim Jaggiff71d202016-04-14 13:12:36 -07001052 }
1053 }
1054 }
1055
1056 /**
1057 * Resets the resizing state of all windows.
1058 */
1059 void endImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001060 for (int j = mChildren.size() - 1; j >= 0; j--) {
1061 mChildren.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Jorim Jaggiff71d202016-04-14 13:12:36 -07001062 }
1063 }
1064
Chong Zhang198afac2016-04-15 12:03:11 -07001065 int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
1066 return displayContentRect.top + (int)
1067 ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
1068 }
1069
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001070 private boolean adjustForIME(final WindowState imeWin) {
1071 final int dockedSide = getDockSide();
1072 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001073 if (imeWin == null || !dockedTopOrBottom) {
1074 return false;
1075 }
1076
1077 final Rect displayContentRect = mTmpRect;
1078 final Rect contentBounds = mTmpRect2;
1079
1080 // Calculate the content bounds excluding the area occupied by IME
1081 getDisplayContent().getContentRect(displayContentRect);
1082 contentBounds.set(displayContentRect);
Jorim Jaggi5ac2ba22016-04-11 21:14:12 -07001083 int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -07001084
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001085 imeTop += imeWin.getGivenContentInsetsLw().top;
1086 if (contentBounds.bottom > imeTop) {
1087 contentBounds.bottom = imeTop;
1088 }
1089
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001090 final int yOffset = displayContentRect.bottom - contentBounds.bottom;
1091
Chong Zhang198afac2016-04-15 12:03:11 -07001092 final int dividerWidth =
1093 getDisplayContent().mDividerControllerLocked.getContentWidth();
1094 final int dividerWidthInactive =
1095 getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
1096
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001097 if (dockedSide == DOCKED_TOP) {
1098 // If this stack is docked on top, we make it smaller so the bottom stack is not
Chong Zhang198afac2016-04-15 12:03:11 -07001099 // occluded by IME. We shift its bottom up by the height of the IME, but
1100 // leaves at least 30% of the top stack visible.
1101 final int minTopStackBottom =
1102 getMinTopStackBottom(displayContentRect, mBounds.bottom);
1103 final int bottom = Math.max(
1104 mBounds.bottom - yOffset + dividerWidth - dividerWidthInactive,
1105 minTopStackBottom);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001106 mTmpAdjustedBounds.set(mBounds);
1107 mTmpAdjustedBounds.bottom =
1108 (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
1109 mFullyAdjustedImeBounds.set(mBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001110 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -07001111 // When the stack is on bottom and has no focus, it's only adjusted for divider width.
1112 final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
1113
1114 // When the stack is on bottom and has focus, it needs to be moved up so as to
1115 // not occluded by IME, and at the same time adjusted for divider width.
1116 // We try to move it up by the height of the IME window, but only to the extent
1117 // that leaves at least 30% of the top stack visible.
1118 // 'top' is where the top of bottom stack will move to in this case.
1119 final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive;
1120 final int minTopStackBottom =
1121 getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
1122 final int top = Math.max(
1123 mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
Chong Zhang198afac2016-04-15 12:03:11 -07001124
Jorim Jaggieb88d832016-04-13 20:17:43 -07001125 mTmpAdjustedBounds.set(mBounds);
Chong Zhangf347ab52016-04-18 21:02:01 -07001126 // Account for the adjustment for IME and divider width separately.
1127 // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
1128 // and dividerWidthDelta is due to divider width change only.
1129 mTmpAdjustedBounds.top = mBounds.top +
1130 (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
1131 mAdjustDividerAmount * dividerWidthDelta);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001132 mFullyAdjustedImeBounds.set(mBounds);
1133 mFullyAdjustedImeBounds.top = top;
1134 mFullyAdjustedImeBounds.bottom = top + mBounds.height();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001135 }
1136 return true;
1137 }
1138
1139 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
1140 final int dockSide = getDockSide();
1141 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
1142 return false;
1143 }
1144
1145 if (dockSide == DOCKED_TOP) {
Winson Chung303c6b72016-10-24 17:12:49 -07001146 mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001147 int topInset = mTmpRect.top;
1148 mTmpAdjustedBounds.set(mBounds);
1149 mTmpAdjustedBounds.bottom =
1150 (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
1151 } else if (dockSide == DOCKED_LEFT) {
1152 mTmpAdjustedBounds.set(mBounds);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001153 final int width = mBounds.width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001154 mTmpAdjustedBounds.right =
1155 (int) (minimizeAmount * mDockedStackMinimizeThickness
1156 + (1 - minimizeAmount) * mBounds.right);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001157 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001158 } else if (dockSide == DOCKED_RIGHT) {
1159 mTmpAdjustedBounds.set(mBounds);
1160 mTmpAdjustedBounds.left =
1161 (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
1162 + (1 - minimizeAmount) * mBounds.left);
1163 }
1164 return true;
1165 }
1166
Matthew Nge15352e2016-12-20 15:36:29 -08001167 private boolean isMinimizedDockAndHomeStackResizable() {
1168 return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
1169 && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
1170 }
1171
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001172 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -08001173 * @return the distance in pixels how much the stack gets minimized from it's original size
1174 */
1175 int getMinimizeDistance() {
1176 final int dockSide = getDockSide();
1177 if (dockSide == DOCKED_INVALID) {
1178 return 0;
1179 }
1180
1181 if (dockSide == DOCKED_TOP) {
Winson Chung303c6b72016-10-24 17:12:49 -07001182 mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggif97ed922016-02-18 18:57:07 -08001183 int topInset = mTmpRect.top;
1184 return mBounds.bottom - topInset;
1185 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
1186 return mBounds.width() - mDockedStackMinimizeThickness;
1187 } else {
1188 return 0;
1189 }
1190 }
1191
1192 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001193 * Updates the adjustment depending on it's current state.
1194 */
Chong Zhang5117e272016-05-03 12:47:34 -07001195 private void updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001196 boolean adjust = false;
1197 if (mMinimizeAmount != 0f) {
1198 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1199 } else if (mAdjustedForIme) {
1200 adjust = adjustForIME(mImeWin);
1201 }
1202 if (!adjust) {
1203 mTmpAdjustedBounds.setEmpty();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001204 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001205 setAdjustedBounds(mTmpAdjustedBounds);
Chong Zhang198afac2016-04-15 12:03:11 -07001206
Chong Zhangb8da4a72016-05-17 15:07:26 -07001207 final boolean isImeTarget = (mService.getImeFocusStackLocked() == this);
Chong Zhangf347ab52016-04-18 21:02:01 -07001208 if (mAdjustedForIme && adjust && !isImeTarget) {
1209 final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
1210 * IME_ADJUST_DIM_AMOUNT;
Wale Ogunwale68278562017-09-23 17:13:55 -07001211 mService.setResizeDimLayer(true, getWindowingMode(), alpha);
Chong Zhang198afac2016-04-15 12:03:11 -07001212 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001213 }
1214
Chong Zhang5117e272016-05-03 12:47:34 -07001215 void applyAdjustForImeIfNeeded(Task task) {
1216 if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) {
1217 return;
1218 }
1219
1220 final Rect insetBounds = mImeGoingAway ? mBounds : mFullyAdjustedImeBounds;
1221 task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001222 mDisplayContent.setLayoutNeeded();
Chong Zhang5117e272016-05-03 12:47:34 -07001223 }
1224
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001225 boolean isAdjustedForMinimizedDockedStack() {
1226 return mMinimizeAmount != 0f;
1227 }
1228
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001229 @CallSuper
1230 @Override
1231 public void writeToProto(ProtoOutputStream proto, long fieldId) {
Steven Timotiusaf03df62017-07-18 16:56:43 -07001232 final long token = proto.start(fieldId);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001233 super.writeToProto(proto, WINDOW_CONTAINER);
Steven Timotiusaf03df62017-07-18 16:56:43 -07001234 proto.write(ID, mStackId);
1235 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
1236 mChildren.get(taskNdx).writeToProto(proto, TASKS);
1237 }
1238 proto.write(FILLS_PARENT, mFillsParent);
1239 mBounds.writeToProto(proto, BOUNDS);
1240 proto.write(ANIMATION_BACKGROUND_SURFACE_IS_DIMMING, mAnimationBackgroundSurface.isDimming());
1241 proto.end(token);
1242 }
1243
Craig Mautner00af9fe2013-03-25 09:13:41 -07001244 public void dump(String prefix, PrintWriter pw) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001245 pw.println(prefix + "mStackId=" + mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -07001246 pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001247 pw.println(prefix + "mFillsParent=" + mFillsParent);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001248 pw.println(prefix + "mBounds=" + mBounds.toShortString());
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001249 if (mMinimizeAmount != 0f) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001250 pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001251 }
1252 if (mAdjustedForIme) {
1253 pw.println(prefix + "mAdjustedForIme=true");
1254 pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
1255 pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
1256 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001257 if (!mAdjustedBounds.isEmpty()) {
1258 pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
1259 }
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001260 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
1261 mChildren.get(taskNdx).dump(prefix + " ", pw);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001262 }
Craig Mautner05d29032013-05-03 13:40:13 -07001263 if (mAnimationBackgroundSurface.isDimming()) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001264 pw.println(prefix + "mWindowAnimationBackgroundSurface:");
Craig Mautner05d29032013-05-03 13:40:13 -07001265 mAnimationBackgroundSurface.printTo(prefix + " ", pw);
1266 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001267 if (!mExitingAppTokens.isEmpty()) {
1268 pw.println();
1269 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001270 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001271 WindowToken token = mExitingAppTokens.get(i);
1272 pw.print(" Exiting App #"); pw.print(i);
1273 pw.print(' '); pw.print(token);
1274 pw.println(':');
1275 token.dump(pw, " ");
1276 }
1277 }
Craig Mautner00af9fe2013-03-25 09:13:41 -07001278 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001279
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001280 /** Fullscreen status of the stack without adjusting for other factors in the system like
1281 * visibility of docked stack.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001282 * Most callers should be using {@link #fillsParent} as it take into consideration other
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001283 * system factors. */
1284 boolean getRawFullscreen() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001285 return mFillsParent;
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001286 }
1287
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001288 @Override
Wale Ogunwale29bfbb82016-05-12 15:13:52 -07001289 public boolean dimFullscreen() {
Wale Ogunwale68278562017-09-23 17:13:55 -07001290 return !isActivityTypeStandard() || fillsParent();
Wale Ogunwale29bfbb82016-05-12 15:13:52 -07001291 }
1292
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001293 @Override
1294 boolean fillsParent() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001295 if (useCurrentBounds()) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001296 return mFillsParent;
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001297 }
1298 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
1299 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
1300 // system.
1301 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001302 }
1303
1304 @Override
1305 public DisplayInfo getDisplayInfo() {
1306 return mDisplayContent.getDisplayInfo();
1307 }
1308
1309 @Override
Wale Ogunwalef0a60a92017-01-19 09:44:40 -08001310 public boolean isAttachedToDisplay() {
1311 return mDisplayContent != null;
1312 }
1313
1314 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001315 public String toString() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001316 return "{stackId=" + mStackId + " tasks=" + mChildren + "}";
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001317 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001318
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001319 String getName() {
1320 return toShortString();
1321 }
1322
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001323 @Override
1324 public String toShortString() {
1325 return "Stack=" + mStackId;
1326 }
1327
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001328 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001329 * For docked workspace (or workspace that's side-by-side to the docked), provides
1330 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001331 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001332 int getDockSide() {
Jorim Jaggi737af722015-12-31 10:42:27 +01001333 return getDockSide(mBounds);
1334 }
1335
Wale Ogunwale926aade2017-08-29 11:24:37 -07001336 private int getDockSide(Rect bounds) {
1337 if (!inSplitScreenWindowingMode()) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001338 return DOCKED_INVALID;
1339 }
1340 if (mDisplayContent == null) {
1341 return DOCKED_INVALID;
1342 }
1343 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Andrii Kulian441e4492016-09-29 15:25:00 -07001344 final int orientation = mDisplayContent.getConfiguration().orientation;
Jorim Jaggi85639432016-05-06 17:27:55 -07001345 return getDockSideUnchecked(bounds, mTmpRect, orientation);
1346 }
1347
1348 static int getDockSideUnchecked(Rect bounds, Rect displayRect, int orientation) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001349 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
1350 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi85639432016-05-06 17:27:55 -07001351 if (bounds.top - displayRect.top <= displayRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001352 return DOCKED_TOP;
1353 } else {
1354 return DOCKED_BOTTOM;
1355 }
1356 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1357 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi85639432016-05-06 17:27:55 -07001358 if (bounds.left - displayRect.left <= displayRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001359 return DOCKED_LEFT;
1360 } else {
1361 return DOCKED_RIGHT;
1362 }
1363 } else {
1364 return DOCKED_INVALID;
1365 }
1366 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001367
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001368 boolean hasTaskForUser(int userId) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001369 for (int i = mChildren.size() - 1; i >= 0; i--) {
1370 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001371 if (task.mUserId == userId) {
1372 return true;
1373 }
1374 }
1375 return false;
1376 }
1377
1378 int taskIdFromPoint(int x, int y) {
1379 getBounds(mTmpRect);
1380 if (!mTmpRect.contains(x, y) || isAdjustedForMinimizedDockedStack()) {
1381 return -1;
1382 }
1383
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001384 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
1385 final Task task = mChildren.get(taskNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001386 final WindowState win = task.getTopVisibleAppMainWindow();
1387 if (win == null) {
1388 continue;
1389 }
1390 // We need to use the task's dim bounds (which is derived from the visible bounds of its
1391 // apps windows) for any touch-related tests. Can't use the task's original bounds
1392 // because it might be adjusted to fit the content frame. For example, the presence of
1393 // the IME adjusting the windows frames when the app window is the IME target.
1394 task.getDimBounds(mTmpRect);
1395 if (mTmpRect.contains(x, y)) {
1396 return task.mTaskId;
1397 }
1398 }
1399
1400 return -1;
1401 }
1402
1403 void findTaskForResizePoint(int x, int y, int delta,
1404 DisplayContent.TaskForResizePointSearchResult results) {
Wale Ogunwale3382ab12017-07-27 08:55:03 -07001405 if (!getWindowConfiguration().canResizeTask()) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001406 results.searchDone = true;
1407 return;
1408 }
1409
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001410 for (int i = mChildren.size() - 1; i >= 0; --i) {
1411 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001412 if (task.isFullscreen()) {
1413 results.searchDone = true;
1414 return;
1415 }
1416
1417 // We need to use the task's dim bounds (which is derived from the visible bounds of
1418 // its apps windows) for any touch-related tests. Can't use the task's original
1419 // bounds because it might be adjusted to fit the content frame. One example is when
1420 // the task is put to top-left quadrant, the actual visible area would not start at
1421 // (0,0) after it's adjusted for the status bar.
1422 task.getDimBounds(mTmpRect);
1423 mTmpRect.inset(-delta, -delta);
1424 if (mTmpRect.contains(x, y)) {
1425 mTmpRect.inset(delta, delta);
1426
1427 results.searchDone = true;
1428
1429 if (!mTmpRect.contains(x, y)) {
1430 results.taskForResize = task;
1431 return;
1432 }
1433 // User touched inside the task. No need to look further,
1434 // focus transfer will be handled in ACTION_UP.
1435 return;
1436 }
1437 }
1438 }
1439
1440 void setTouchExcludeRegion(Task focusedTask, int delta, Region touchExcludeRegion,
1441 Rect contentRect, Rect postExclude) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001442 for (int i = mChildren.size() - 1; i >= 0; --i) {
1443 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001444 AppWindowToken token = task.getTopVisibleAppToken();
1445 if (token == null || !token.hasContentToDisplay()) {
1446 continue;
1447 }
1448
1449 /**
1450 * Exclusion region is the region that TapDetector doesn't care about.
1451 * Here we want to remove all non-focused tasks from the exclusion region.
1452 * We also remove the outside touch area for resizing for all freeform
1453 * tasks (including the focused).
1454 *
1455 * We save the focused task region once we find it, and add it back at the end.
Matthew Nge15352e2016-12-20 15:36:29 -08001456 *
1457 * If the task is home stack and it is resizable in the minimized state, we want to
1458 * exclude the docked stack from touch so we need the entire screen area and not just a
1459 * small portion which the home stack currently is resized to.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001460 */
1461
Wale Ogunwale6fbde9f2017-08-24 07:24:12 -07001462 if (task.isActivityTypeHome() && isMinimizedDockAndHomeStackResizable()) {
Matthew Nge15352e2016-12-20 15:36:29 -08001463 mDisplayContent.getLogicalDisplayRect(mTmpRect);
1464 } else {
1465 task.getDimBounds(mTmpRect);
1466 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001467
1468 if (task == focusedTask) {
1469 // Add the focused task rect back into the exclude region once we are done
1470 // processing stacks.
1471 postExclude.set(mTmpRect);
1472 }
1473
1474 final boolean isFreeformed = task.inFreeformWorkspace();
1475 if (task != focusedTask || isFreeformed) {
1476 if (isFreeformed) {
1477 // If the task is freeformed, enlarge the area to account for outside
1478 // touch area for resize.
1479 mTmpRect.inset(-delta, -delta);
1480 // Intersect with display content rect. If we have system decor (status bar/
1481 // navigation bar), we want to exclude that from the tap detection.
1482 // Otherwise, if the app is partially placed under some system button (eg.
1483 // Recents, Home), pressing that button would cause a full series of
1484 // unwanted transfer focus/resume/pause, before we could go home.
1485 mTmpRect.intersect(contentRect);
1486 }
1487 touchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
1488 }
1489 }
1490 }
1491
Winson Chung8bca9e42017-04-16 15:59:43 -07001492 public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
1493 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
1494 synchronized (mService.mWindowMap) {
1495 if (mCancelCurrentBoundsAnimation) {
1496 return false;
1497 }
Winson Chung19953ca2017-04-11 11:19:23 -07001498 }
1499
Robert Carr0d00c2e2016-02-29 17:45:02 -08001500 try {
Winson Chung8bca9e42017-04-16 15:59:43 -07001501 mService.mActivityManager.resizePinnedStack(stackBounds, tempTaskBounds);
Robert Carr0d00c2e2016-02-29 17:45:02 -08001502 } catch (RemoteException e) {
1503 // I don't believe you.
1504 }
1505 return true;
1506 }
1507
Robert Carrecc06b32017-04-18 14:25:10 -07001508 void onAllWindowsDrawn() {
Winson Chunge7ba6862017-05-24 12:13:33 -07001509 if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
Robert Carrecc06b32017-04-18 14:25:10 -07001510 return;
1511 }
1512
1513 mService.mBoundsAnimationController.onAllWindowsDrawn();
1514 }
1515
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001516 @Override // AnimatesBounds
Winson Chungab76bbc2017-08-14 13:33:51 -07001517 public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001518 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001519 synchronized (mService.mWindowMap) {
Winson Chung40a5f932017-04-13 16:39:36 -07001520 mBoundsAnimatingRequested = false;
Robert Carr1ca6a332016-04-11 18:00:43 -07001521 mBoundsAnimating = true;
Winson Chung19953ca2017-04-11 11:19:23 -07001522 mCancelCurrentBoundsAnimation = false;
Robert Carrecc06b32017-04-18 14:25:10 -07001523
1524 // If we are changing UI mode, as in the PiP to fullscreen
1525 // transition, then we need to wait for the window to draw.
1526 if (schedulePipModeChangedCallback) {
1527 forAllWindows((w) -> { w.mWinAnimator.resetDrawState(); },
1528 false /* traverseTopToBottom */);
1529 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001530 }
Winson Chung85d39982017-02-24 15:21:25 -08001531
1532 if (mStackId == PINNED_STACK_ID) {
1533 try {
1534 mService.mActivityManager.notifyPinnedStackAnimationStarted();
1535 } catch (RemoteException e) {
1536 // I don't believe you...
1537 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001538
1539 final PinnedStackWindowController controller =
1540 (PinnedStackWindowController) getController();
1541 if (schedulePipModeChangedCallback && controller != null) {
Winson Chungab76bbc2017-08-14 13:33:51 -07001542 // We need to schedule the PiP mode change before the animation up. It is possible
1543 // in this case for the animation down to not have been completed, so always
1544 // force-schedule and update to the client to ensure that it is notified that it
1545 // is no longer in picture-in-picture mode
1546 controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
Winson Chung8bca9e42017-04-16 15:59:43 -07001547 }
Winson Chung85d39982017-02-24 15:21:25 -08001548 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001549 }
1550
1551 @Override // AnimatesBounds
Winson Chung8bca9e42017-04-16 15:59:43 -07001552 public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
1553 boolean moveToFullscreen) {
1554 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Wale Ogunwalece144522016-02-05 22:51:01 -08001555 synchronized (mService.mWindowMap) {
Robert Carr1ca6a332016-04-11 18:00:43 -07001556 mBoundsAnimating = false;
Robert Carr18f622f2017-05-08 11:20:43 -07001557 for (int i = 0; i < mChildren.size(); i++) {
1558 final Task t = mChildren.get(i);
1559 t.clearPreserveNonFloatingState();
1560 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001561 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001562 }
Winson Chung85d39982017-02-24 15:21:25 -08001563
Wale Ogunwale480dca02016-02-06 13:58:29 -08001564 if (mStackId == PINNED_STACK_ID) {
Robert Carr18f622f2017-05-08 11:20:43 -07001565 // Update to the final bounds if requested. This is done here instead of in the bounds
1566 // animator to allow us to coordinate this after we notify the PiP mode changed
1567
Winson Chung8bca9e42017-04-16 15:59:43 -07001568 final PinnedStackWindowController controller =
1569 (PinnedStackWindowController) getController();
1570 if (schedulePipModeChangedCallback && controller != null) {
1571 // We need to schedule the PiP mode change after the animation down, so use the
1572 // final bounds
1573 controller.updatePictureInPictureModeForPinnedStackAnimation(
Winson Chungab76bbc2017-08-14 13:33:51 -07001574 mBoundsAnimationTarget, false /* forceUpdate */);
Winson Chung8bca9e42017-04-16 15:59:43 -07001575 }
1576
Winson Chung8bca9e42017-04-16 15:59:43 -07001577 if (finalStackSize != null) {
1578 setPinnedStackSize(finalStackSize, null);
1579 }
1580
Wale Ogunwale480dca02016-02-06 13:58:29 -08001581 try {
1582 mService.mActivityManager.notifyPinnedStackAnimationEnded();
Winson Chung8bca9e42017-04-16 15:59:43 -07001583 if (moveToFullscreen) {
1584 mService.mActivityManager.moveTasksToFullscreenStack(mStackId,
1585 true /* onTop */);
1586 }
Wale Ogunwale480dca02016-02-06 13:58:29 -08001587 } catch (RemoteException e) {
1588 // I don't believe you...
1589 }
1590 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001591 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001592
Winson Chung8bca9e42017-04-16 15:59:43 -07001593 /**
1594 * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
1595 * bounds and we have a deferred PiP mode changed callback set with the animation.
1596 */
1597 public boolean deferScheduleMultiWindowModeChanged() {
1598 if (mStackId == PINNED_STACK_ID) {
1599 return (mBoundsAnimatingRequested || mBoundsAnimating);
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001600 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001601 return false;
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001602 }
1603
Robert Carr8f0a3ad2017-02-15 19:30:28 -08001604 public boolean isForceScaled() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001605 return mBoundsAnimating;
1606 }
1607
Winson Chung40a5f932017-04-13 16:39:36 -07001608 public boolean isAnimatingBounds() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001609 return mBoundsAnimating;
Robert Carr0d00c2e2016-02-29 17:45:02 -08001610 }
Jorim Jaggi6626f542016-08-22 13:08:44 -07001611
Robert Carr18f622f2017-05-08 11:20:43 -07001612 public boolean lastAnimatingBoundsWasToFullscreen() {
1613 return mBoundsAnimatingToFullscreen;
1614 }
1615
Winson Chung40a5f932017-04-13 16:39:36 -07001616 public boolean isAnimatingBoundsToFullscreen() {
Robert Carr18f622f2017-05-08 11:20:43 -07001617 return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
Robert Carr7e4c90e2017-02-15 19:52:38 -08001618 }
1619
Winson Chung8bca9e42017-04-16 15:59:43 -07001620 public boolean pinnedStackResizeDisallowed() {
Winson Chung19953ca2017-04-11 11:19:23 -07001621 if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
1622 return true;
1623 }
1624 return false;
1625 }
1626
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001627 /** Returns true if a removal action is still being deferred. */
1628 boolean checkCompleteDeferredRemoval() {
1629 if (isAnimating()) {
1630 return true;
1631 }
Wale Ogunwale10124582016-09-15 20:25:50 -07001632 if (mDeferRemoval) {
1633 removeImmediately();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001634 }
1635
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001636 return super.checkCompleteDeferredRemoval();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001637 }
1638
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001639 void stepAppWindowsAnimation(long currentTime) {
1640 super.stepAppWindowsAnimation(currentTime);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001641
1642 // TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
1643 // below but is set in the loop above. See if it really matters...
Wale Ogunwale48458e12017-06-06 10:07:58 -07001644
1645 // Clear before using.
1646 mTmpAppTokens.clear();
1647 // We copy the list as things can be removed from the exiting token list while we are
1648 // processing.
1649 mTmpAppTokens.addAll(mExitingAppTokens);
1650 for (int i = 0; i < mTmpAppTokens.size(); i++) {
1651 final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001652 appAnimator.wasAnimating = appAnimator.animating;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001653 if (appAnimator.stepAnimationLocked(currentTime)) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001654 mService.mAnimator.setAnimating(true);
1655 mService.mAnimator.mAppWindowAnimating = true;
1656 } else if (appAnimator.wasAnimating) {
1657 // stopped animating, do one more pass through the layout
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001658 appAnimator.mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
1659 "exiting appToken " + appAnimator.mAppToken + " done");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001660 if (DEBUG_ANIM) Slog.v(TAG_WM,
1661 "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
1662 }
1663 }
Wale Ogunwale48458e12017-06-06 10:07:58 -07001664 // Clear to avoid holding reference to tokens.
1665 mTmpAppTokens.clear();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001666 }
1667
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001668 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07001669 int getOrientation() {
Wale Ogunwale68278562017-09-23 17:13:55 -07001670 return (canSpecifyOrientation()) ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
1671 }
1672
1673 private boolean canSpecifyOrientation() {
1674 final int windowingMode = getWindowingMode();
1675 final int activityType = getActivityType();
1676 return windowingMode == WINDOWING_MODE_FULLSCREEN
1677 || activityType == ACTIVITY_TYPE_HOME
1678 || activityType == ACTIVITY_TYPE_RECENTS
1679 || activityType == ACTIVITY_TYPE_ASSISTANT;
Wale Ogunwale51362492016-09-08 17:49:17 -07001680 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001681}