blob: 55151a192fbff42cce5e649e25c1f652f0c92bbb [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;
Jorim Jaggid3ec5072016-04-28 15:57:47 -070022import static android.app.ActivityManager.StackId.HOME_STACK_ID;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070023import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Wale Ogunwale51362492016-09-08 17:49:17 -070024import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070025import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
26import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Winson Chung303c6b72016-10-24 17:12:49 -070027import static android.view.Display.DEFAULT_DISPLAY;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070028import static android.view.WindowManager.DOCKED_BOTTOM;
29import static android.view.WindowManager.DOCKED_INVALID;
30import static android.view.WindowManager.DOCKED_LEFT;
31import static android.view.WindowManager.DOCKED_RIGHT;
32import static android.view.WindowManager.DOCKED_TOP;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -070033import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
Jorim Jaggiff71d202016-04-14 13:12:36 -070034import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -070035import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070036import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
37import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -070038import static com.android.server.wm.WindowManagerService.LAYER_OFFSET_DIM;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070039
Wale Ogunwale3797c222015-10-27 14:21:58 -070040import android.app.ActivityManager.StackId;
Wale Ogunwale60454db2015-01-23 16:05:07 -080041import android.content.res.Configuration;
Craig Mautner05d29032013-05-03 13:40:13 -070042import android.graphics.Rect;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -070043import android.graphics.Region;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080044import android.os.RemoteException;
Craig Mautner2c2549c2013-11-12 08:31:15 -080045import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070046import android.util.Slog;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070047import android.util.SparseArray;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070048import android.view.DisplayInfo;
Wale Ogunwale94744212015-09-21 19:01:47 -070049import android.view.Surface;
Filip Gruszczynski54977fe2015-10-19 17:26:45 -070050
Jorim Jaggi737af722015-12-31 10:42:27 +010051import com.android.internal.policy.DividerSnapAlgorithm;
52import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
53import com.android.internal.policy.DockedDividerUtils;
Craig Mautner2c2549c2013-11-12 08:31:15 -080054import com.android.server.EventLogTags;
Robert Carrecc06b32017-04-18 14:25:10 -070055import com.android.server.UiThread;
Craig Mautner05d29032013-05-03 13:40:13 -070056
Craig Mautner00af9fe2013-03-25 09:13:41 -070057import java.io.PrintWriter;
Craig Mautnerc00204b2013-03-05 15:02:14 -080058
Wale Ogunwale14a3fb92016-09-11 15:19:05 -070059public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLayerUser,
Winson Chung8bca9e42017-04-16 15:59:43 -070060 BoundsAnimationTarget {
Chong Zhang198afac2016-04-15 12:03:11 -070061 /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
62 * restrict IME adjustment so that a min portion of top stack remains visible.*/
63 private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
64
65 /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
66 private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070067
Craig Mautner00af9fe2013-03-25 09:13:41 -070068 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080069 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070070
Craig Mautner05d29032013-05-03 13:40:13 -070071 /** The service */
72 private final WindowManagerService mService;
73
Craig Mautner00af9fe2013-03-25 09:13:41 -070074 /** The display this stack sits under. */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -070075 // TODO: Track parent marks like this in WindowContainer.
Craig Mautnerdf88d732014-01-27 09:21:32 -080076 private DisplayContent mDisplayContent;
Craig Mautner00af9fe2013-03-25 09:13:41 -070077
Craig Mautnerb660b9d2014-02-13 10:59:16 -080078 /** For comparison with DisplayContent bounds. */
79 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070080 private Rect mTmpRect2 = new Rect();
Winson Chung19953ca2017-04-11 11:19:23 -070081 private Rect mTmpRect3 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -080082
83 /** Content limits relative to the DisplayContent this sits in. */
84 private Rect mBounds = new Rect();
85
Chong Zhangb816b862016-01-25 12:01:12 -080086 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
87 private final Rect mAdjustedBounds = new Rect();
88
Jorim Jaggieb88d832016-04-13 20:17:43 -070089 /**
90 * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
91 * represent the state when the animation has ended.
92 */
93 private final Rect mFullyAdjustedImeBounds = new Rect();
94
Craig Mautnerb660b9d2014-02-13 10:59:16 -080095 /** Whether mBounds is fullscreen */
Wale Ogunwale14a3fb92016-09-11 15:19:05 -070096 private boolean mFillsParent = true;
Craig Mautnerc00204b2013-03-05 15:02:14 -080097
Wale Ogunwale94744212015-09-21 19:01:47 -070098 // Device rotation as of the last time {@link #mBounds} was set.
Wale Ogunwale02319a62016-09-26 15:21:22 -070099 private int mRotation;
Wale Ogunwale94744212015-09-21 19:01:47 -0700100
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700101 /** Density as of last time {@link #mBounds} was set. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700102 private int mDensity;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700103
Craig Mautner05d29032013-05-03 13:40:13 -0700104 /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700105 private DimLayer mAnimationBackgroundSurface;
Craig Mautner05d29032013-05-03 13:40:13 -0700106
107 /** The particular window with an Animation with non-zero background color. */
Wale Ogunwale02319a62016-09-26 15:21:22 -0700108 private WindowStateAnimator mAnimationBackgroundAnimator;
Craig Mautner05d29032013-05-03 13:40:13 -0700109
Craig Mautnerdc548482014-02-05 13:35:24 -0800110 /** Application tokens that are exiting, but still on screen for animations. */
111 final AppTokenList mExitingAppTokens = new AppTokenList();
Wale Ogunwale48458e12017-06-06 10:07:58 -0700112 final AppTokenList mTmpAppTokens = new AppTokenList();
Craig Mautnerdc548482014-02-05 13:35:24 -0800113
Craig Mautner95da1082014-02-24 17:54:35 -0800114 /** Detach this stack from its display when animation completes. */
Wale Ogunwalef6192862016-09-10 13:42:30 -0700115 // TODO: maybe tie this to WindowContainer#removeChild some how...
Wale Ogunwale10124582016-09-15 20:25:50 -0700116 boolean mDeferRemoval;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800117
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800118 private final Rect mTmpAdjustedBounds = new Rect();
119 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700120 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800121 private WindowState mImeWin;
122 private float mMinimizeAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700123 private float mAdjustImeAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700124 private float mAdjustDividerAmount;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800125 private final int mDockedStackMinimizeThickness;
126
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700127 // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
128 // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
129 // would otherwise apply while resizing, while resizing in the bounds animating mode.
Robert Carr1ca6a332016-04-11 18:00:43 -0700130 private boolean mBoundsAnimating = false;
Winson Chung40a5f932017-04-13 16:39:36 -0700131 // Set when an animation has been requested but has not yet started from the UI thread. This is
132 // cleared when the animation actually starts.
133 private boolean mBoundsAnimatingRequested = false;
Robert Carr7e4c90e2017-02-15 19:52:38 -0800134 private boolean mBoundsAnimatingToFullscreen = false;
Winson Chung19953ca2017-04-11 11:19:23 -0700135 private boolean mCancelCurrentBoundsAnimation = false;
Winson Chung84a38342016-11-08 16:15:10 -0800136 private Rect mBoundsAnimationTarget = new Rect();
Winson Chung8bca9e42017-04-16 15:59:43 -0700137 private Rect mBoundsAnimationSourceHintBounds = new Rect();
Robert Carr0d00c2e2016-02-29 17:45:02 -0800138
Chong Zhang167bbfac2016-03-31 09:44:34 -0700139 // Temporary storage for the new bounds that should be used after the configuration change.
140 // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
141 private final Rect mBoundsAfterRotation = new Rect();
142
Robert Carr18f622f2017-05-08 11:20:43 -0700143 Rect mPreAnimationBounds = new Rect();
144
Craig Mautnerdf88d732014-01-27 09:21:32 -0800145 TaskStack(WindowManagerService service, int stackId) {
Craig Mautner05d29032013-05-03 13:40:13 -0700146 mService = service;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800147 mStackId = stackId;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800148 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
149 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700150 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800151 }
152
153 DisplayContent getDisplayContent() {
154 return mDisplayContent;
155 }
156
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700157 Task findHomeTask() {
158 if (mStackId != HOME_STACK_ID) {
159 return null;
160 }
161
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700162 for (int i = mChildren.size() - 1; i >= 0; i--) {
163 if (mChildren.get(i).isHomeTask()) {
164 return mChildren.get(i);
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700165 }
166 }
167 return null;
168 }
169
Wale Ogunwale15ead902016-09-02 14:30:11 -0700170 boolean hasMultipleTaskWithHomeTaskNotTop() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700171 return mChildren.size() > 1 && !mChildren.get(mChildren.size() - 1).isHomeTask();
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 Ogunwale3797c222015-10-27 14:21:58 -0700297 || !StackId.isResizeableByDockedStack(mStackId)
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
Jorim Jaggi65002e12016-04-21 18:25:49 -0700692 || (dockedStack != null && StackId.isResizeableByDockedStack(mStackId)
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 Ogunwale649c1602017-04-24 10:15:31 -0700741 if (mStackId == HOME_STACK_ID) {
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 Ogunwalea9f9b372016-02-04 18:04:39 -0800764 if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
765 || mDisplayContent == null) {
Matthew Ngaa2b6202017-02-10 14:48:21 -0800766 outStackBounds.set(mBounds);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700767 return;
768 }
769
Wale Ogunwale1666e312016-12-16 11:27:18 -0800770 final TaskStack dockedStack = mDisplayContent.getDockedStackIgnoringVisibility();
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700771 if (dockedStack == null) {
772 // Not sure why you are calling this method when there is no docked stack...
773 throw new IllegalStateException(
774 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
775 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700776 if (!ignoreVisibility && !dockedStack.isVisible()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700777 // The docked stack is being dismissed, but we caught before it finished being
778 // dismissed. In that case we want to treat it as if it is not occupying any space and
779 // let others occupy the whole display.
Matthew Ngaa2b6202017-02-10 14:48:21 -0800780 mDisplayContent.getLogicalDisplayRect(outStackBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700781 return;
782 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700783
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700784 final int dockedSide = dockedStack.getDockSide();
785 if (dockedSide == DOCKED_INVALID) {
786 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800787 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Matthew Ngaa2b6202017-02-10 14:48:21 -0800788 outStackBounds.set(mBounds);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700789 return;
790 }
791
792 mDisplayContent.getLogicalDisplayRect(mTmpRect);
793 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800794 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Matthew Ngaa2b6202017-02-10 14:48:21 -0800795 getStackDockedModeBounds(mTmpRect, outStackBounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100796 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700797
798 }
799
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700800 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700801 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700802 * @param displayRect The bounds of the display the docked stack is on.
803 * @param outBounds Output bounds that should be used for the stack.
804 * @param stackId Id of stack we are calculating the bounds for.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700805 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700806 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
807 * close to the side of the dock.
808 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700809 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800810 private void getStackDockedModeBounds(
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700811 Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
812 boolean dockOnTopOrLeft) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700813 final boolean dockedStack = stackId == DOCKED_STACK_ID;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700814 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700815
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700816 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700817 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800818 if (mService.mDockedStackCreateBounds != null) {
819 outBounds.set(mService.mDockedStackCreateBounds);
820 return;
821 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100822
823 // The initial bounds of the docked stack when it is created about half the screen space
824 // and its bounds can be adjusted after that. The bounds of all other stacks are
825 // adjusted to occupy whatever screen space the docked stack isn't occupying.
826 final DisplayInfo di = mDisplayContent.getDisplayInfo();
827 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
828 mTmpRect2);
829 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100830 di.logicalWidth,
831 di.logicalHeight,
832 dockDividerWidth,
Andrii Kulian441e4492016-09-29 15:25:00 -0700833 mDisplayContent.getConfiguration().orientation == ORIENTATION_PORTRAIT,
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100834 mTmpRect2).getMiddleTarget().position;
835
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700836 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700837 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100838 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700839 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100840 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700841 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700842 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700843 if (splitHorizontally) {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700844 outBounds.left = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700845 } else {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700846 outBounds.top = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700847 }
848 }
849 return;
850 }
851
852 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700853 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700854 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700855 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700856 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700857 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700858 }
859 } else {
860 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700861 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700862 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700863 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700864 }
865 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800866 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700867 }
868
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800869 void resetDockedStackToMiddle() {
870 if (mStackId != DOCKED_STACK_ID) {
871 throw new IllegalStateException("Not a docked stack=" + this);
872 }
873
874 mService.mDockedStackCreateBounds = null;
875
876 final Rect bounds = new Rect();
Matthew Nge15352e2016-12-20 15:36:29 -0800877 final Rect tempBounds = new Rect();
Matthew Ngaa2b6202017-02-10 14:48:21 -0800878 getStackDockedModeBoundsLocked(null /* currentTempTaskBounds */, bounds, tempBounds,
879 true /*ignoreVisibility*/);
Wale Ogunwale1666e312016-12-16 11:27:18 -0800880 getController().requestResize(bounds);
881 }
882
883 @Override
884 StackWindowController getController() {
885 return (StackWindowController) super.getController();
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800886 }
887
Wale Ogunwale10124582016-09-15 20:25:50 -0700888 @Override
889 void removeIfPossible() {
890 if (isAnimating()) {
891 mDeferRemoval = true;
892 return;
893 }
894 removeImmediately();
895 }
896
897 @Override
898 void removeImmediately() {
899 super.removeImmediately();
900
Andrii Kulian839def92016-11-02 10:58:58 -0700901 onRemovedFromDisplay();
902 }
903
904 /**
905 * Removes the stack it from its current parent, so it can be either destroyed completely or
906 * re-parented.
907 */
908 void onRemovedFromDisplay() {
Wale Ogunwale10124582016-09-15 20:25:50 -0700909 mDisplayContent.mDimLayerController.removeDimLayerUser(this);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800910 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -0700911
912 if (mAnimationBackgroundSurface != null) {
913 mAnimationBackgroundSurface.destroySurface();
914 mAnimationBackgroundSurface = null;
915 }
Wale Ogunwale10124582016-09-15 20:25:50 -0700916
917 if (mStackId == DOCKED_STACK_ID) {
Andrii Kulian839def92016-11-02 10:58:58 -0700918 mDisplayContent.mDividerControllerLocked.notifyDockedStackExistsChanged(false);
Wale Ogunwale10124582016-09-15 20:25:50 -0700919 }
Andrii Kulian839def92016-11-02 10:58:58 -0700920
921 mDisplayContent = null;
922 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700923 }
924
Craig Mautner05d29032013-05-03 13:40:13 -0700925 void resetAnimationBackgroundAnimator() {
926 mAnimationBackgroundAnimator = null;
927 mAnimationBackgroundSurface.hide();
928 }
929
Craig Mautner05d29032013-05-03 13:40:13 -0700930 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
931 int animLayer = winAnimator.mAnimLayer;
932 if (mAnimationBackgroundAnimator == null
933 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
934 mAnimationBackgroundAnimator = winAnimator;
Wale Ogunwaleae9adbf2016-10-18 15:17:06 -0700935 animLayer = mDisplayContent.getLayerForAnimationBackground(winAnimator);
936 mAnimationBackgroundSurface.show(animLayer - LAYER_OFFSET_DIM,
Craig Mautner05d29032013-05-03 13:40:13 -0700937 ((color >> 24) & 0xff) / 255f, 0);
938 }
939 }
940
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700941 // TODO: Should each user have there own stacks?
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000942 @Override
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800943 void switchUser() {
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000944 super.switchUser();
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700945 int top = mChildren.size();
Craig Mautnerac6f8432013-07-17 13:24:59 -0700946 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700947 Task task = mChildren.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700948 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -0700949 mChildren.remove(taskNdx);
950 mChildren.add(task);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700951 --top;
952 }
953 }
954 }
955
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800956 /**
957 * Adjusts the stack bounds if the IME is visible.
958 *
959 * @param imeWin The IME window.
960 */
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700961 void setAdjustedForIme(WindowState imeWin, boolean forceUpdate) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800962 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -0700963 mImeGoingAway = false;
Keisuke Kuroyanagi19d9a8f2016-05-12 16:49:02 -0700964 if (!mAdjustedForIme || forceUpdate) {
Jorim Jaggiff71d202016-04-14 13:12:36 -0700965 mAdjustedForIme = true;
966 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -0700967 mAdjustDividerAmount = 0f;
968 updateAdjustForIme(0f, 0f, true /* force */);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700969 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700970 }
971
972 boolean isAdjustedForIme() {
Chong Zhang5117e272016-05-03 12:47:34 -0700973 return mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700974 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700975
976 boolean isAnimatingForIme() {
977 return mImeWin != null && mImeWin.isAnimatingLw();
978 }
979
980 /**
981 * Update the stack's bounds (crop or position) according to the IME window's
982 * current position. When IME window is animated, the bottom stack is animated
983 * together to track the IME window's current position, and the top stack is
984 * cropped as necessary.
985 *
986 * @return true if a traversal should be performed after the adjustment.
987 */
Chong Zhangf347ab52016-04-18 21:02:01 -0700988 boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
989 if (adjustAmount != mAdjustImeAmount
990 || adjustDividerAmount != mAdjustDividerAmount || force) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700991 mAdjustImeAmount = adjustAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700992 mAdjustDividerAmount = adjustDividerAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700993 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +0200994 return isVisible();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700995 } else {
996 return false;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700997 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800998 }
999
1000 /**
1001 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -07001002 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
1003 * animations; otherwise, set flag and animates the window away together
1004 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001005 */
Chong Zhangbaba7832016-03-24 10:21:26 -07001006 void resetAdjustedForIme(boolean adjustBoundsNow) {
1007 if (adjustBoundsNow) {
1008 mImeWin = null;
1009 mAdjustedForIme = false;
1010 mImeGoingAway = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -07001011 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -07001012 mAdjustDividerAmount = 0f;
Chong Zhangbaba7832016-03-24 10:21:26 -07001013 updateAdjustedBounds();
Chong Zhang198afac2016-04-15 12:03:11 -07001014 mService.setResizeDimLayer(false, mStackId, 1.0f);
Chong Zhangbaba7832016-03-24 10:21:26 -07001015 } else {
1016 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001017 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001018 }
1019
1020 /**
1021 * Sets the amount how much we currently minimize our stack.
1022 *
1023 * @param minimizeAmount The amount, between 0 and 1.
1024 * @return Whether the amount has changed and a layout is needed.
1025 */
1026 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
1027 if (minimizeAmount != mMinimizeAmount) {
1028 mMinimizeAmount = minimizeAmount;
1029 updateAdjustedBounds();
Jorim Jaggife762342016-10-13 14:33:27 +02001030 return isVisible();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001031 } else {
1032 return false;
1033 }
1034 }
1035
Matthew Nge15352e2016-12-20 15:36:29 -08001036 boolean shouldIgnoreInput() {
1037 return isAdjustedForMinimizedDockedStack() || mStackId == DOCKED_STACK_ID &&
1038 isMinimizedDockAndHomeStackResizable();
Jorim Jaggi409635b2016-04-01 15:32:28 -07001039 }
1040
Jorim Jaggiff71d202016-04-14 13:12:36 -07001041 /**
1042 * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
1043 * to the list of to be drawn windows the service is waiting for.
1044 */
1045 void beginImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001046 for (int j = mChildren.size() - 1; j >= 0; j--) {
1047 final Task task = mChildren.get(j);
Wale Ogunwale44f21802016-09-02 12:49:48 -07001048 if (task.hasContentToDisplay()) {
Jorim Jaggiff71d202016-04-14 13:12:36 -07001049 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Wale Ogunwale9f25bee2016-08-02 07:23:47 -07001050 task.setWaitingForDrawnIfResizingChanged();
Jorim Jaggiff71d202016-04-14 13:12:36 -07001051 }
1052 }
1053 }
1054
1055 /**
1056 * Resets the resizing state of all windows.
1057 */
1058 void endImeAdjustAnimation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001059 for (int j = mChildren.size() - 1; j >= 0; j--) {
1060 mChildren.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
Jorim Jaggiff71d202016-04-14 13:12:36 -07001061 }
1062 }
1063
Chong Zhang198afac2016-04-15 12:03:11 -07001064 int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
1065 return displayContentRect.top + (int)
1066 ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
1067 }
1068
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001069 private boolean adjustForIME(final WindowState imeWin) {
1070 final int dockedSide = getDockSide();
1071 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001072 if (imeWin == null || !dockedTopOrBottom) {
1073 return false;
1074 }
1075
1076 final Rect displayContentRect = mTmpRect;
1077 final Rect contentBounds = mTmpRect2;
1078
1079 // Calculate the content bounds excluding the area occupied by IME
1080 getDisplayContent().getContentRect(displayContentRect);
1081 contentBounds.set(displayContentRect);
Jorim Jaggi5ac2ba22016-04-11 21:14:12 -07001082 int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -07001083
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001084 imeTop += imeWin.getGivenContentInsetsLw().top;
1085 if (contentBounds.bottom > imeTop) {
1086 contentBounds.bottom = imeTop;
1087 }
1088
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001089 final int yOffset = displayContentRect.bottom - contentBounds.bottom;
1090
Chong Zhang198afac2016-04-15 12:03:11 -07001091 final int dividerWidth =
1092 getDisplayContent().mDividerControllerLocked.getContentWidth();
1093 final int dividerWidthInactive =
1094 getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
1095
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001096 if (dockedSide == DOCKED_TOP) {
1097 // If this stack is docked on top, we make it smaller so the bottom stack is not
Chong Zhang198afac2016-04-15 12:03:11 -07001098 // occluded by IME. We shift its bottom up by the height of the IME, but
1099 // leaves at least 30% of the top stack visible.
1100 final int minTopStackBottom =
1101 getMinTopStackBottom(displayContentRect, mBounds.bottom);
1102 final int bottom = Math.max(
1103 mBounds.bottom - yOffset + dividerWidth - dividerWidthInactive,
1104 minTopStackBottom);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001105 mTmpAdjustedBounds.set(mBounds);
1106 mTmpAdjustedBounds.bottom =
1107 (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
1108 mFullyAdjustedImeBounds.set(mBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001109 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -07001110 // When the stack is on bottom and has no focus, it's only adjusted for divider width.
1111 final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
1112
1113 // When the stack is on bottom and has focus, it needs to be moved up so as to
1114 // not occluded by IME, and at the same time adjusted for divider width.
1115 // We try to move it up by the height of the IME window, but only to the extent
1116 // that leaves at least 30% of the top stack visible.
1117 // 'top' is where the top of bottom stack will move to in this case.
1118 final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive;
1119 final int minTopStackBottom =
1120 getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
1121 final int top = Math.max(
1122 mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
Chong Zhang198afac2016-04-15 12:03:11 -07001123
Jorim Jaggieb88d832016-04-13 20:17:43 -07001124 mTmpAdjustedBounds.set(mBounds);
Chong Zhangf347ab52016-04-18 21:02:01 -07001125 // Account for the adjustment for IME and divider width separately.
1126 // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
1127 // and dividerWidthDelta is due to divider width change only.
1128 mTmpAdjustedBounds.top = mBounds.top +
1129 (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
1130 mAdjustDividerAmount * dividerWidthDelta);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001131 mFullyAdjustedImeBounds.set(mBounds);
1132 mFullyAdjustedImeBounds.top = top;
1133 mFullyAdjustedImeBounds.bottom = top + mBounds.height();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001134 }
1135 return true;
1136 }
1137
1138 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
1139 final int dockSide = getDockSide();
1140 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
1141 return false;
1142 }
1143
1144 if (dockSide == DOCKED_TOP) {
Winson Chung303c6b72016-10-24 17:12:49 -07001145 mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001146 int topInset = mTmpRect.top;
1147 mTmpAdjustedBounds.set(mBounds);
1148 mTmpAdjustedBounds.bottom =
1149 (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
1150 } else if (dockSide == DOCKED_LEFT) {
1151 mTmpAdjustedBounds.set(mBounds);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001152 final int width = mBounds.width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001153 mTmpAdjustedBounds.right =
1154 (int) (minimizeAmount * mDockedStackMinimizeThickness
1155 + (1 - minimizeAmount) * mBounds.right);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001156 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001157 } else if (dockSide == DOCKED_RIGHT) {
1158 mTmpAdjustedBounds.set(mBounds);
1159 mTmpAdjustedBounds.left =
1160 (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
1161 + (1 - minimizeAmount) * mBounds.left);
1162 }
1163 return true;
1164 }
1165
Matthew Nge15352e2016-12-20 15:36:29 -08001166 private boolean isMinimizedDockAndHomeStackResizable() {
1167 return mDisplayContent.mDividerControllerLocked.isMinimizedDock()
1168 && mDisplayContent.mDividerControllerLocked.isHomeStackResizable();
1169 }
1170
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001171 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -08001172 * @return the distance in pixels how much the stack gets minimized from it's original size
1173 */
1174 int getMinimizeDistance() {
1175 final int dockSide = getDockSide();
1176 if (dockSide == DOCKED_INVALID) {
1177 return 0;
1178 }
1179
1180 if (dockSide == DOCKED_TOP) {
Winson Chung303c6b72016-10-24 17:12:49 -07001181 mService.getStableInsetsLocked(DEFAULT_DISPLAY, mTmpRect);
Jorim Jaggif97ed922016-02-18 18:57:07 -08001182 int topInset = mTmpRect.top;
1183 return mBounds.bottom - topInset;
1184 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
1185 return mBounds.width() - mDockedStackMinimizeThickness;
1186 } else {
1187 return 0;
1188 }
1189 }
1190
1191 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001192 * Updates the adjustment depending on it's current state.
1193 */
Chong Zhang5117e272016-05-03 12:47:34 -07001194 private void updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001195 boolean adjust = false;
1196 if (mMinimizeAmount != 0f) {
1197 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1198 } else if (mAdjustedForIme) {
1199 adjust = adjustForIME(mImeWin);
1200 }
1201 if (!adjust) {
1202 mTmpAdjustedBounds.setEmpty();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001203 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001204 setAdjustedBounds(mTmpAdjustedBounds);
Chong Zhang198afac2016-04-15 12:03:11 -07001205
Chong Zhangb8da4a72016-05-17 15:07:26 -07001206 final boolean isImeTarget = (mService.getImeFocusStackLocked() == this);
Chong Zhangf347ab52016-04-18 21:02:01 -07001207 if (mAdjustedForIme && adjust && !isImeTarget) {
1208 final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
1209 * IME_ADJUST_DIM_AMOUNT;
Chong Zhang198afac2016-04-15 12:03:11 -07001210 mService.setResizeDimLayer(true, mStackId, alpha);
1211 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001212 }
1213
Chong Zhang5117e272016-05-03 12:47:34 -07001214 void applyAdjustForImeIfNeeded(Task task) {
1215 if (mMinimizeAmount != 0f || !mAdjustedForIme || mAdjustedBounds.isEmpty()) {
1216 return;
1217 }
1218
1219 final Rect insetBounds = mImeGoingAway ? mBounds : mFullyAdjustedImeBounds;
1220 task.alignToAdjustedBounds(mAdjustedBounds, insetBounds, getDockSide() == DOCKED_TOP);
Wale Ogunwale2b06bfc2016-09-28 14:17:05 -07001221 mDisplayContent.setLayoutNeeded();
Chong Zhang5117e272016-05-03 12:47:34 -07001222 }
1223
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001224 boolean isAdjustedForMinimizedDockedStack() {
1225 return mMinimizeAmount != 0f;
1226 }
1227
Craig Mautner00af9fe2013-03-25 09:13:41 -07001228 public void dump(String prefix, PrintWriter pw) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001229 pw.println(prefix + "mStackId=" + mStackId);
Wale Ogunwale10124582016-09-15 20:25:50 -07001230 pw.println(prefix + "mDeferRemoval=" + mDeferRemoval);
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001231 pw.println(prefix + "mFillsParent=" + mFillsParent);
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001232 pw.println(prefix + "mBounds=" + mBounds.toShortString());
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001233 if (mMinimizeAmount != 0f) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001234 pw.println(prefix + "mMinimizeAmount=" + mMinimizeAmount);
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001235 }
1236 if (mAdjustedForIme) {
1237 pw.println(prefix + "mAdjustedForIme=true");
1238 pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
1239 pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
1240 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001241 if (!mAdjustedBounds.isEmpty()) {
1242 pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
1243 }
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001244 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; taskNdx--) {
1245 mChildren.get(taskNdx).dump(prefix + " ", pw);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001246 }
Craig Mautner05d29032013-05-03 13:40:13 -07001247 if (mAnimationBackgroundSurface.isDimming()) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001248 pw.println(prefix + "mWindowAnimationBackgroundSurface:");
Craig Mautner05d29032013-05-03 13:40:13 -07001249 mAnimationBackgroundSurface.printTo(prefix + " ", pw);
1250 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001251 if (!mExitingAppTokens.isEmpty()) {
1252 pw.println();
1253 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001254 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001255 WindowToken token = mExitingAppTokens.get(i);
1256 pw.print(" Exiting App #"); pw.print(i);
1257 pw.print(' '); pw.print(token);
1258 pw.println(':');
1259 token.dump(pw, " ");
1260 }
1261 }
Craig Mautner00af9fe2013-03-25 09:13:41 -07001262 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001263
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001264 /** Fullscreen status of the stack without adjusting for other factors in the system like
1265 * visibility of docked stack.
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001266 * Most callers should be using {@link #fillsParent} as it take into consideration other
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001267 * system factors. */
1268 boolean getRawFullscreen() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001269 return mFillsParent;
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001270 }
1271
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001272 @Override
Wale Ogunwale29bfbb82016-05-12 15:13:52 -07001273 public boolean dimFullscreen() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001274 return StackId.isHomeOrRecentsStack(mStackId) || fillsParent();
Wale Ogunwale29bfbb82016-05-12 15:13:52 -07001275 }
1276
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001277 @Override
1278 boolean fillsParent() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001279 if (useCurrentBounds()) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001280 return mFillsParent;
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001281 }
1282 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
1283 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
1284 // system.
1285 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001286 }
1287
1288 @Override
1289 public DisplayInfo getDisplayInfo() {
1290 return mDisplayContent.getDisplayInfo();
1291 }
1292
1293 @Override
Wale Ogunwalef0a60a92017-01-19 09:44:40 -08001294 public boolean isAttachedToDisplay() {
1295 return mDisplayContent != null;
1296 }
1297
1298 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001299 public String toString() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001300 return "{stackId=" + mStackId + " tasks=" + mChildren + "}";
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001301 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001302
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001303 String getName() {
1304 return toShortString();
1305 }
1306
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001307 @Override
1308 public String toShortString() {
1309 return "Stack=" + mStackId;
1310 }
1311
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001312 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001313 * For docked workspace (or workspace that's side-by-side to the docked), provides
1314 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001315 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001316 int getDockSide() {
Jorim Jaggi737af722015-12-31 10:42:27 +01001317 return getDockSide(mBounds);
1318 }
1319
1320 int getDockSide(Rect bounds) {
Chong Zhangc806d902015-11-30 09:44:27 -08001321 if (mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId)) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001322 return DOCKED_INVALID;
1323 }
1324 if (mDisplayContent == null) {
1325 return DOCKED_INVALID;
1326 }
1327 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Andrii Kulian441e4492016-09-29 15:25:00 -07001328 final int orientation = mDisplayContent.getConfiguration().orientation;
Jorim Jaggi85639432016-05-06 17:27:55 -07001329 return getDockSideUnchecked(bounds, mTmpRect, orientation);
1330 }
1331
1332 static int getDockSideUnchecked(Rect bounds, Rect displayRect, int orientation) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001333 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
1334 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi85639432016-05-06 17:27:55 -07001335 if (bounds.top - displayRect.top <= displayRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001336 return DOCKED_TOP;
1337 } else {
1338 return DOCKED_BOTTOM;
1339 }
1340 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1341 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi85639432016-05-06 17:27:55 -07001342 if (bounds.left - displayRect.left <= displayRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001343 return DOCKED_LEFT;
1344 } else {
1345 return DOCKED_RIGHT;
1346 }
1347 } else {
1348 return DOCKED_INVALID;
1349 }
1350 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001351
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001352 boolean hasTaskForUser(int userId) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001353 for (int i = mChildren.size() - 1; i >= 0; i--) {
1354 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001355 if (task.mUserId == userId) {
1356 return true;
1357 }
1358 }
1359 return false;
1360 }
1361
1362 int taskIdFromPoint(int x, int y) {
1363 getBounds(mTmpRect);
1364 if (!mTmpRect.contains(x, y) || isAdjustedForMinimizedDockedStack()) {
1365 return -1;
1366 }
1367
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001368 for (int taskNdx = mChildren.size() - 1; taskNdx >= 0; --taskNdx) {
1369 final Task task = mChildren.get(taskNdx);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001370 final WindowState win = task.getTopVisibleAppMainWindow();
1371 if (win == null) {
1372 continue;
1373 }
1374 // We need to use the task's dim bounds (which is derived from the visible bounds of its
1375 // apps windows) for any touch-related tests. Can't use the task's original bounds
1376 // because it might be adjusted to fit the content frame. For example, the presence of
1377 // the IME adjusting the windows frames when the app window is the IME target.
1378 task.getDimBounds(mTmpRect);
1379 if (mTmpRect.contains(x, y)) {
1380 return task.mTaskId;
1381 }
1382 }
1383
1384 return -1;
1385 }
1386
1387 void findTaskForResizePoint(int x, int y, int delta,
1388 DisplayContent.TaskForResizePointSearchResult results) {
1389 if (!StackId.isTaskResizeAllowed(mStackId)) {
1390 results.searchDone = true;
1391 return;
1392 }
1393
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001394 for (int i = mChildren.size() - 1; i >= 0; --i) {
1395 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001396 if (task.isFullscreen()) {
1397 results.searchDone = true;
1398 return;
1399 }
1400
1401 // We need to use the task's dim bounds (which is derived from the visible bounds of
1402 // its apps windows) for any touch-related tests. Can't use the task's original
1403 // bounds because it might be adjusted to fit the content frame. One example is when
1404 // the task is put to top-left quadrant, the actual visible area would not start at
1405 // (0,0) after it's adjusted for the status bar.
1406 task.getDimBounds(mTmpRect);
1407 mTmpRect.inset(-delta, -delta);
1408 if (mTmpRect.contains(x, y)) {
1409 mTmpRect.inset(delta, delta);
1410
1411 results.searchDone = true;
1412
1413 if (!mTmpRect.contains(x, y)) {
1414 results.taskForResize = task;
1415 return;
1416 }
1417 // User touched inside the task. No need to look further,
1418 // focus transfer will be handled in ACTION_UP.
1419 return;
1420 }
1421 }
1422 }
1423
1424 void setTouchExcludeRegion(Task focusedTask, int delta, Region touchExcludeRegion,
1425 Rect contentRect, Rect postExclude) {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001426 for (int i = mChildren.size() - 1; i >= 0; --i) {
1427 final Task task = mChildren.get(i);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001428 AppWindowToken token = task.getTopVisibleAppToken();
1429 if (token == null || !token.hasContentToDisplay()) {
1430 continue;
1431 }
1432
1433 /**
1434 * Exclusion region is the region that TapDetector doesn't care about.
1435 * Here we want to remove all non-focused tasks from the exclusion region.
1436 * We also remove the outside touch area for resizing for all freeform
1437 * tasks (including the focused).
1438 *
1439 * We save the focused task region once we find it, and add it back at the end.
Matthew Nge15352e2016-12-20 15:36:29 -08001440 *
1441 * If the task is home stack and it is resizable in the minimized state, we want to
1442 * exclude the docked stack from touch so we need the entire screen area and not just a
1443 * small portion which the home stack currently is resized to.
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001444 */
1445
Matthew Nge15352e2016-12-20 15:36:29 -08001446 if (task.isHomeTask() && isMinimizedDockAndHomeStackResizable()) {
1447 mDisplayContent.getLogicalDisplayRect(mTmpRect);
1448 } else {
1449 task.getDimBounds(mTmpRect);
1450 }
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001451
1452 if (task == focusedTask) {
1453 // Add the focused task rect back into the exclude region once we are done
1454 // processing stacks.
1455 postExclude.set(mTmpRect);
1456 }
1457
1458 final boolean isFreeformed = task.inFreeformWorkspace();
1459 if (task != focusedTask || isFreeformed) {
1460 if (isFreeformed) {
1461 // If the task is freeformed, enlarge the area to account for outside
1462 // touch area for resize.
1463 mTmpRect.inset(-delta, -delta);
1464 // Intersect with display content rect. If we have system decor (status bar/
1465 // navigation bar), we want to exclude that from the tap detection.
1466 // Otherwise, if the app is partially placed under some system button (eg.
1467 // Recents, Home), pressing that button would cause a full series of
1468 // unwanted transfer focus/resume/pause, before we could go home.
1469 mTmpRect.intersect(contentRect);
1470 }
1471 touchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
1472 }
1473 }
1474 }
1475
Winson Chung8bca9e42017-04-16 15:59:43 -07001476 public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
1477 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
1478 synchronized (mService.mWindowMap) {
1479 if (mCancelCurrentBoundsAnimation) {
1480 return false;
1481 }
Winson Chung19953ca2017-04-11 11:19:23 -07001482 }
1483
Robert Carr0d00c2e2016-02-29 17:45:02 -08001484 try {
Winson Chung8bca9e42017-04-16 15:59:43 -07001485 mService.mActivityManager.resizePinnedStack(stackBounds, tempTaskBounds);
Robert Carr0d00c2e2016-02-29 17:45:02 -08001486 } catch (RemoteException e) {
1487 // I don't believe you.
1488 }
1489 return true;
1490 }
1491
Robert Carrecc06b32017-04-18 14:25:10 -07001492 void onAllWindowsDrawn() {
Winson Chunge7ba6862017-05-24 12:13:33 -07001493 if (!mBoundsAnimating && !mBoundsAnimatingRequested) {
Robert Carrecc06b32017-04-18 14:25:10 -07001494 return;
1495 }
1496
1497 mService.mBoundsAnimationController.onAllWindowsDrawn();
1498 }
1499
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001500 @Override // AnimatesBounds
Winson Chungab76bbc2017-08-14 13:33:51 -07001501 public void onAnimationStart(boolean schedulePipModeChangedCallback, boolean forceUpdate) {
Winson Chung8bca9e42017-04-16 15:59:43 -07001502 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001503 synchronized (mService.mWindowMap) {
Winson Chung40a5f932017-04-13 16:39:36 -07001504 mBoundsAnimatingRequested = false;
Robert Carr1ca6a332016-04-11 18:00:43 -07001505 mBoundsAnimating = true;
Winson Chung19953ca2017-04-11 11:19:23 -07001506 mCancelCurrentBoundsAnimation = false;
Robert Carrecc06b32017-04-18 14:25:10 -07001507
1508 // If we are changing UI mode, as in the PiP to fullscreen
1509 // transition, then we need to wait for the window to draw.
1510 if (schedulePipModeChangedCallback) {
1511 forAllWindows((w) -> { w.mWinAnimator.resetDrawState(); },
1512 false /* traverseTopToBottom */);
1513 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001514 }
Winson Chung85d39982017-02-24 15:21:25 -08001515
1516 if (mStackId == PINNED_STACK_ID) {
1517 try {
1518 mService.mActivityManager.notifyPinnedStackAnimationStarted();
1519 } catch (RemoteException e) {
1520 // I don't believe you...
1521 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001522
1523 final PinnedStackWindowController controller =
1524 (PinnedStackWindowController) getController();
1525 if (schedulePipModeChangedCallback && controller != null) {
Winson Chungab76bbc2017-08-14 13:33:51 -07001526 // We need to schedule the PiP mode change before the animation up. It is possible
1527 // in this case for the animation down to not have been completed, so always
1528 // force-schedule and update to the client to ensure that it is notified that it
1529 // is no longer in picture-in-picture mode
1530 controller.updatePictureInPictureModeForPinnedStackAnimation(null, forceUpdate);
Winson Chung8bca9e42017-04-16 15:59:43 -07001531 }
Winson Chung85d39982017-02-24 15:21:25 -08001532 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001533 }
1534
1535 @Override // AnimatesBounds
Winson Chung8bca9e42017-04-16 15:59:43 -07001536 public void onAnimationEnd(boolean schedulePipModeChangedCallback, Rect finalStackSize,
1537 boolean moveToFullscreen) {
1538 // Hold the lock since this is called from the BoundsAnimator running on the UiThread
Wale Ogunwalece144522016-02-05 22:51:01 -08001539 synchronized (mService.mWindowMap) {
Robert Carr1ca6a332016-04-11 18:00:43 -07001540 mBoundsAnimating = false;
Robert Carr18f622f2017-05-08 11:20:43 -07001541 for (int i = 0; i < mChildren.size(); i++) {
1542 final Task t = mChildren.get(i);
1543 t.clearPreserveNonFloatingState();
1544 }
Wale Ogunwalece144522016-02-05 22:51:01 -08001545 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001546 }
Winson Chung85d39982017-02-24 15:21:25 -08001547
Wale Ogunwale480dca02016-02-06 13:58:29 -08001548 if (mStackId == PINNED_STACK_ID) {
Robert Carr18f622f2017-05-08 11:20:43 -07001549 // Update to the final bounds if requested. This is done here instead of in the bounds
1550 // animator to allow us to coordinate this after we notify the PiP mode changed
1551
Winson Chung8bca9e42017-04-16 15:59:43 -07001552 final PinnedStackWindowController controller =
1553 (PinnedStackWindowController) getController();
1554 if (schedulePipModeChangedCallback && controller != null) {
1555 // We need to schedule the PiP mode change after the animation down, so use the
1556 // final bounds
1557 controller.updatePictureInPictureModeForPinnedStackAnimation(
Winson Chungab76bbc2017-08-14 13:33:51 -07001558 mBoundsAnimationTarget, false /* forceUpdate */);
Winson Chung8bca9e42017-04-16 15:59:43 -07001559 }
1560
Winson Chung8bca9e42017-04-16 15:59:43 -07001561 if (finalStackSize != null) {
1562 setPinnedStackSize(finalStackSize, null);
1563 }
1564
Wale Ogunwale480dca02016-02-06 13:58:29 -08001565 try {
1566 mService.mActivityManager.notifyPinnedStackAnimationEnded();
Winson Chung8bca9e42017-04-16 15:59:43 -07001567 if (moveToFullscreen) {
1568 mService.mActivityManager.moveTasksToFullscreenStack(mStackId,
1569 true /* onTop */);
1570 }
Wale Ogunwale480dca02016-02-06 13:58:29 -08001571 } catch (RemoteException e) {
1572 // I don't believe you...
1573 }
1574 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001575 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001576
Winson Chung8bca9e42017-04-16 15:59:43 -07001577 /**
1578 * @return True if we are currently animating the pinned stack from fullscreen to non-fullscreen
1579 * bounds and we have a deferred PiP mode changed callback set with the animation.
1580 */
1581 public boolean deferScheduleMultiWindowModeChanged() {
1582 if (mStackId == PINNED_STACK_ID) {
1583 return (mBoundsAnimatingRequested || mBoundsAnimating);
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001584 }
Winson Chung8bca9e42017-04-16 15:59:43 -07001585 return false;
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001586 }
1587
Robert Carrc7294602016-05-13 11:32:05 -07001588 public boolean hasMovementAnimations() {
1589 return StackId.hasMovementAnimations(mStackId);
Robert Carr0d00c2e2016-02-29 17:45:02 -08001590 }
1591
Robert Carr8f0a3ad2017-02-15 19:30:28 -08001592 public boolean isForceScaled() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001593 return mBoundsAnimating;
1594 }
1595
Winson Chung40a5f932017-04-13 16:39:36 -07001596 public boolean isAnimatingBounds() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001597 return mBoundsAnimating;
Robert Carr0d00c2e2016-02-29 17:45:02 -08001598 }
Jorim Jaggi6626f542016-08-22 13:08:44 -07001599
Robert Carr18f622f2017-05-08 11:20:43 -07001600 public boolean lastAnimatingBoundsWasToFullscreen() {
1601 return mBoundsAnimatingToFullscreen;
1602 }
1603
Winson Chung40a5f932017-04-13 16:39:36 -07001604 public boolean isAnimatingBoundsToFullscreen() {
Robert Carr18f622f2017-05-08 11:20:43 -07001605 return isAnimatingBounds() && lastAnimatingBoundsWasToFullscreen();
Robert Carr7e4c90e2017-02-15 19:52:38 -08001606 }
1607
Winson Chung8bca9e42017-04-16 15:59:43 -07001608 public boolean pinnedStackResizeDisallowed() {
Winson Chung19953ca2017-04-11 11:19:23 -07001609 if (mBoundsAnimating && mCancelCurrentBoundsAnimation) {
1610 return true;
1611 }
1612 return false;
1613 }
1614
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001615 /** Returns true if a removal action is still being deferred. */
1616 boolean checkCompleteDeferredRemoval() {
1617 if (isAnimating()) {
1618 return true;
1619 }
Wale Ogunwale10124582016-09-15 20:25:50 -07001620 if (mDeferRemoval) {
1621 removeImmediately();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001622 }
1623
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001624 return super.checkCompleteDeferredRemoval();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001625 }
1626
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001627 void stepAppWindowsAnimation(long currentTime) {
1628 super.stepAppWindowsAnimation(currentTime);
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001629
1630 // TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
1631 // below but is set in the loop above. See if it really matters...
Wale Ogunwale48458e12017-06-06 10:07:58 -07001632
1633 // Clear before using.
1634 mTmpAppTokens.clear();
1635 // We copy the list as things can be removed from the exiting token list while we are
1636 // processing.
1637 mTmpAppTokens.addAll(mExitingAppTokens);
1638 for (int i = 0; i < mTmpAppTokens.size(); i++) {
1639 final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001640 appAnimator.wasAnimating = appAnimator.animating;
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001641 if (appAnimator.stepAnimationLocked(currentTime)) {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001642 mService.mAnimator.setAnimating(true);
1643 mService.mAnimator.mAppWindowAnimating = true;
1644 } else if (appAnimator.wasAnimating) {
1645 // stopped animating, do one more pass through the layout
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001646 appAnimator.mAppToken.setAppLayoutChanges(FINISH_LAYOUT_REDO_WALLPAPER,
1647 "exiting appToken " + appAnimator.mAppToken + " done");
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001648 if (DEBUG_ANIM) Slog.v(TAG_WM,
1649 "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
1650 }
1651 }
Wale Ogunwale48458e12017-06-06 10:07:58 -07001652 // Clear to avoid holding reference to tokens.
1653 mTmpAppTokens.clear();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001654 }
1655
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001656 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -07001657 int getOrientation() {
Wale Ogunwale14a3fb92016-09-11 15:19:05 -07001658 return (StackId.canSpecifyOrientation(mStackId))
1659 ? super.getOrientation() : SCREEN_ORIENTATION_UNSET;
Wale Ogunwale51362492016-09-08 17:49:17 -07001660 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001661}