blob: 6c80d1ab3cfec7c16796e9f33ccdc20c4cb5486d [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;
20import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
Jorim Jaggid3ec5072016-04-28 15:57:47 -070021import static android.app.ActivityManager.StackId.HOME_STACK_ID;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070022import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
23import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
24import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
25import static android.view.WindowManager.DOCKED_BOTTOM;
26import static android.view.WindowManager.DOCKED_INVALID;
27import static android.view.WindowManager.DOCKED_LEFT;
28import static android.view.WindowManager.DOCKED_RIGHT;
29import static android.view.WindowManager.DOCKED_TOP;
Jorim Jaggiff71d202016-04-14 13:12:36 -070030import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070031import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
32import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
33import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
34
Wale Ogunwale3797c222015-10-27 14:21:58 -070035import android.app.ActivityManager.StackId;
Wale Ogunwale60454db2015-01-23 16:05:07 -080036import android.content.res.Configuration;
Craig Mautner05d29032013-05-03 13:40:13 -070037import android.graphics.Rect;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070038import android.os.Debug;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080039import android.os.RemoteException;
Craig Mautner2c2549c2013-11-12 08:31:15 -080040import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070041import android.util.Slog;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070042import android.util.SparseArray;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070043import android.view.DisplayInfo;
Wale Ogunwale94744212015-09-21 19:01:47 -070044import android.view.Surface;
Robert Carr1ca6a332016-04-11 18:00:43 -070045import android.view.SurfaceControl;
Filip Gruszczynski54977fe2015-10-19 17:26:45 -070046
Jorim Jaggi737af722015-12-31 10:42:27 +010047import com.android.internal.policy.DividerSnapAlgorithm;
48import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
49import com.android.internal.policy.DockedDividerUtils;
Craig Mautner2c2549c2013-11-12 08:31:15 -080050import com.android.server.EventLogTags;
Craig Mautner05d29032013-05-03 13:40:13 -070051
Craig Mautner00af9fe2013-03-25 09:13:41 -070052import java.io.PrintWriter;
Craig Mautnerc00204b2013-03-05 15:02:14 -080053import java.util.ArrayList;
54
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080055public class TaskStack implements DimLayer.DimLayerUser,
56 BoundsAnimationController.AnimateBoundsUser {
Chong Zhang198afac2016-04-15 12:03:11 -070057 /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
58 * restrict IME adjustment so that a min portion of top stack remains visible.*/
59 private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
60
61 /** Dimming amount for non-focused stack when stacks are IME-adjusted. */
62 private static final float IME_ADJUST_DIM_AMOUNT = 0.25f;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070063
Craig Mautner00af9fe2013-03-25 09:13:41 -070064 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080065 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070066
Craig Mautner05d29032013-05-03 13:40:13 -070067 /** The service */
68 private final WindowManagerService mService;
69
Craig Mautner00af9fe2013-03-25 09:13:41 -070070 /** The display this stack sits under. */
Craig Mautnerdf88d732014-01-27 09:21:32 -080071 private DisplayContent mDisplayContent;
Craig Mautner00af9fe2013-03-25 09:13:41 -070072
73 /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match
74 * mTaskHistory in the ActivityStack with the same mStackId */
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070075 private final ArrayList<Task> mTasks = new ArrayList<>();
Craig Mautner00af9fe2013-03-25 09:13:41 -070076
Craig Mautnerb660b9d2014-02-13 10:59:16 -080077 /** For comparison with DisplayContent bounds. */
78 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070079 private Rect mTmpRect2 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -080080
81 /** Content limits relative to the DisplayContent this sits in. */
82 private Rect mBounds = new Rect();
83
Chong Zhangb816b862016-01-25 12:01:12 -080084 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
85 private final Rect mAdjustedBounds = new Rect();
86
Jorim Jaggieb88d832016-04-13 20:17:43 -070087 /**
88 * Fully adjusted IME bounds. These are different from {@link #mAdjustedBounds} because they
89 * represent the state when the animation has ended.
90 */
91 private final Rect mFullyAdjustedImeBounds = new Rect();
92
Craig Mautnerb660b9d2014-02-13 10:59:16 -080093 /** Whether mBounds is fullscreen */
94 private boolean mFullscreen = true;
Craig Mautnerc00204b2013-03-05 15:02:14 -080095
Wale Ogunwale94744212015-09-21 19:01:47 -070096 // Device rotation as of the last time {@link #mBounds} was set.
97 int mRotation;
98
Jorim Jaggi11c62e12016-04-05 20:41:21 -070099 /** Density as of last time {@link #mBounds} was set. */
100 int mDensity;
101
Craig Mautner05d29032013-05-03 13:40:13 -0700102 /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
Craig Mautnerdf88d732014-01-27 09:21:32 -0800103 DimLayer mAnimationBackgroundSurface;
Craig Mautner05d29032013-05-03 13:40:13 -0700104
105 /** The particular window with an Animation with non-zero background color. */
106 WindowStateAnimator mAnimationBackgroundAnimator;
107
Craig Mautnerdc548482014-02-05 13:35:24 -0800108 /** Application tokens that are exiting, but still on screen for animations. */
109 final AppTokenList mExitingAppTokens = new AppTokenList();
110
Craig Mautner95da1082014-02-24 17:54:35 -0800111 /** Detach this stack from its display when animation completes. */
112 boolean mDeferDetach;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800113
Wale Ogunwalece144522016-02-05 22:51:01 -0800114 // Whether the stack and all its tasks is currently being drag-resized
115 private boolean mDragResizing;
116
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800117 private final Rect mTmpAdjustedBounds = new Rect();
118 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700119 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800120 private WindowState mImeWin;
121 private float mMinimizeAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700122 private float mAdjustImeAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700123 private float mAdjustDividerAmount;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800124 private final int mDockedStackMinimizeThickness;
125
Robert Carr1ca6a332016-04-11 18:00:43 -0700126 // If this is true, we are in the bounds animating mode.
127 // The task will be down or upscaled to perfectly fit the
128 // region it would have been cropped to. We may also avoid
129 // certain logic we would otherwise apply while resizing,
130 // while resizing in the bounds animating mode.
131 private boolean mBoundsAnimating = false;
Robert Carr0d00c2e2016-02-29 17:45:02 -0800132 // By default, movement animations are applied to all
133 // window movement. If this is true, animations will not
134 // be applied within this stack. This is useful for example
135 // if the windows are moving as the result of a stack animation,
136 // in which case a second window animation would cause jitter.
137 private boolean mFreezeMovementAnimations = false;
138
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
Craig Mautnerdf88d732014-01-27 09:21:32 -0800143 TaskStack(WindowManagerService service, int stackId) {
Craig Mautner05d29032013-05-03 13:40:13 -0700144 mService = service;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800145 mStackId = stackId;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800146 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
147 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700148 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800149 }
150
151 DisplayContent getDisplayContent() {
152 return mDisplayContent;
153 }
154
Craig Mautnerd9a22882013-03-16 15:00:36 -0700155 ArrayList<Task> getTasks() {
156 return mTasks;
157 }
158
Jorim Jaggid3ec5072016-04-28 15:57:47 -0700159 Task findHomeTask() {
160 if (mStackId != HOME_STACK_ID) {
161 return null;
162 }
163
164 for (int i = mTasks.size() - 1; i >= 0; i--) {
165 if (mTasks.get(i).isHomeTask()) {
166 return mTasks.get(i);
167 }
168 }
169 return null;
170 }
171
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700172 /**
173 * Set the bounds of the stack and its containing tasks.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700174 * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700175 * @param configs Configuration for individual tasks, keyed by task id.
176 * @param taskBounds Bounds for individual tasks, keyed by task id.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700177 * @return True if the stack bounds was changed.
178 * */
Wale Ogunwalea6e902e2015-09-21 18:37:15 -0700179 boolean setBounds(
Jorim Jaggidc249c42015-12-15 14:57:31 -0800180 Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
181 SparseArray<Rect> taskTempInsetBounds) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500182 setBounds(stackBounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700183
184 // Update bounds of containing tasks.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700185 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
186 final Task task = mTasks.get(taskNdx);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700187 Configuration config = configs.get(task.mTaskId);
188 if (config != null) {
189 Rect bounds = taskBounds.get(task.mTaskId);
Chong Zhang2a88fc32016-01-11 17:14:24 -0800190 if (task.isTwoFingerScrollMode()) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800191 // This is a non-resizeable task that's docked (or side-by-side to the docked
192 // stack). It might have been scrolled previously, and after the stack resizing,
193 // it might no longer fully cover the stack area.
194 // Save the old bounds and re-apply the scroll. This adjusts the bounds to
195 // fit the new stack bounds.
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100196 task.resizeLocked(bounds, config, false /* forced */);
Chong Zhangf66db432016-01-13 10:39:51 -0800197 task.getBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800198 task.scrollLocked(mTmpRect);
199 } else {
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100200 task.resizeLocked(bounds, config, false /* forced */);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800201 task.setTempInsetBounds(
202 taskTempInsetBounds != null ? taskTempInsetBounds.get(task.mTaskId)
203 : null);
Chong Zhangb15758a2015-11-17 12:12:03 -0800204 }
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700205 } else {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800206 Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700207 }
208 }
209 return true;
210 }
211
Jorim Jaggi0429f352015-12-22 16:29:16 +0100212 void prepareFreezingTaskBounds() {
213 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
214 final Task task = mTasks.get(taskNdx);
215 task.prepareFreezingBounds();
216 }
217 }
218
Wale Ogunwaleb4ec0a32015-12-14 10:31:43 -0800219 boolean isFullscreenBounds(Rect bounds) {
220 if (mDisplayContent == null || bounds == null) {
221 return true;
222 }
223 mDisplayContent.getLogicalDisplayRect(mTmpRect);
224 return mTmpRect.equals(bounds);
225 }
226
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800227 /**
228 * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
229 * the normal task bounds.
230 *
231 * @param bounds The adjusted bounds.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800232 */
Jorim Jaggieb88d832016-04-13 20:17:43 -0700233 private void setAdjustedBounds(Rect bounds) {
234 if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
235 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800236 }
237
238 mAdjustedBounds.set(bounds);
239 final boolean adjusted = !mAdjustedBounds.isEmpty();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700240 Rect insetBounds = null;
241 if (adjusted && isAdjustedForMinimizedDock()) {
242 insetBounds = mBounds;
243 } else if (adjusted && isAdjustedForIme()) {
244 if (mImeGoingAway) {
245 insetBounds = mBounds;
246 } else {
247 insetBounds = mFullyAdjustedImeBounds;
248 }
249 }
250 alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800251 mDisplayContent.layoutNeeded = true;
252 }
253
254 private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
Chong Zhangb816b862016-01-25 12:01:12 -0800255 if (mFullscreen) {
256 return;
257 }
258 // Update bounds of containing tasks.
259 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
260 final Task task = mTasks.get(taskNdx);
261 if (task.isTwoFingerScrollMode()) {
262 // If we're scrolling we don't care about your bounds or configs,
263 // they should be null as if we were in fullscreen.
264 task.resizeLocked(null, null, false /* forced */);
265 task.getBounds(mTmpRect2);
266 task.scrollLocked(mTmpRect2);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800267 } else if (task.isResizeable() && task.mOverrideConfig != Configuration.EMPTY) {
Chong Zhangb816b862016-01-25 12:01:12 -0800268 task.getBounds(mTmpRect2);
Chong Zhang198afac2016-04-15 12:03:11 -0700269 if (mAdjustedForIme && getDockSide() == DOCKED_TOP) {
270 int offsetY = adjustedBounds.bottom - mTmpRect2.bottom;
271 mTmpRect2.offset(0, offsetY);
272 } else {
273 mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
274 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800275 task.setTempInsetBounds(tempInsetBounds);
Chong Zhangb816b862016-01-25 12:01:12 -0800276 task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */);
277 }
278 }
279 }
280
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700281 private boolean setBounds(Rect bounds) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800282 boolean oldFullscreen = mFullscreen;
Wale Ogunwale94744212015-09-21 19:01:47 -0700283 int rotation = Surface.ROTATION_0;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700284 int density = DENSITY_DPI_UNDEFINED;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800285 if (mDisplayContent != null) {
286 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwale94744212015-09-21 19:01:47 -0700287 rotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700288 density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
Jorim Jaggi067e8172016-02-03 18:24:12 -0800289 mFullscreen = bounds == null;
290 if (mFullscreen) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800291 bounds = mTmpRect;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800292 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800293 }
294
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800295 if (bounds == null) {
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800296 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800297 return false;
298 }
Wale Ogunwale94744212015-09-21 19:01:47 -0700299 if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800300 return false;
301 }
302
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700303 if (mDisplayContent != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800304 mDisplayContent.mDimLayerController.updateDimLayer(this);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700305 mAnimationBackgroundSurface.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700306 }
307
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800308 mBounds.set(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700309 mRotation = rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700310 mDensity = density;
Chong Zhangb816b862016-01-25 12:01:12 -0800311
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800312 updateAdjustedBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800313
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800314 return true;
315 }
316
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700317 /** Bounds of the stack without adjusting for other factors in the system like visibility
318 * of docked stack.
319 * Most callers should be using {@link #getBounds} as it take into consideration other system
320 * factors. */
321 void getRawBounds(Rect out) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800322 out.set(mBounds);
323 }
324
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700325 /** Return true if the current bound can get outputted to the rest of the system as-is. */
326 private boolean useCurrentBounds() {
327 if (mFullscreen
Wale Ogunwale3797c222015-10-27 14:21:58 -0700328 || !StackId.isResizeableByDockedStack(mStackId)
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700329 || mDisplayContent == null
330 || mDisplayContent.getDockedStackLocked() != null) {
331 return true;
332 }
333 return false;
334 }
335
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700336 public void getBounds(Rect out) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700337 if (useCurrentBounds()) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800338 // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
339 // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
340 // stack is visible since it is already what we want to represent to the rest of the
341 // system.
342 if (!mAdjustedBounds.isEmpty()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800343 out.set(mAdjustedBounds);
344 } else {
345 out.set(mBounds);
346 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700347 return;
348 }
349
350 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
351 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
352 // system.
353 mDisplayContent.getLogicalDisplayRect(out);
354 }
355
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800356 /** Bounds of the stack with other system factors taken into consideration. */
357 @Override
358 public void getDimBounds(Rect out) {
359 getBounds(out);
360 }
361
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700362 void updateDisplayInfo(Rect bounds) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800363 if (mDisplayContent == null) {
364 return;
365 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100366
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800367 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
368 mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
369 }
370 if (bounds != null) {
371 setBounds(bounds);
372 return;
373 } else if (mFullscreen) {
374 setBounds(null);
375 return;
376 }
377
378 mTmpRect2.set(mBounds);
379 final int newRotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700380 final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
381 if (mRotation == newRotation && mDensity == newDensity) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800382 setBounds(mTmpRect2);
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800383 }
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700384
385 // If the rotation or density didn't match, we'll update it in onConfigurationChanged.
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800386 }
387
Chong Zhang167bbfac2016-03-31 09:44:34 -0700388 boolean onConfigurationChanged() {
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700389 return updateBoundsAfterConfigChange();
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800390 }
391
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700392 private boolean updateBoundsAfterConfigChange() {
Wale Ogunwale5952f9a2016-04-25 13:40:30 -0700393 if (mFullscreen) {
394 // Bounds will already be set correctly when display info is updated in the case of
395 // fullscreen.
396 return false;
397 }
398
Jorim Jaggi737af722015-12-31 10:42:27 +0100399 final int newRotation = getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700400 final int newDensity = getDisplayInfo().logicalDensityDpi;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800401
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700402 if (mRotation == newRotation && mDensity == newDensity) {
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700403 // Nothing to do here as we already update the state in updateDisplayInfo.
Chong Zhang167bbfac2016-03-31 09:44:34 -0700404 return false;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800405 }
406
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700407 final int oldDockSide = mStackId == DOCKED_STACK_ID ? getDockSide() : DOCKED_INVALID;
Wale Ogunwale5952f9a2016-04-25 13:40:30 -0700408 mTmpRect2.set(mBounds);
Jorim Jaggi737af722015-12-31 10:42:27 +0100409 mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
410 if (mStackId == DOCKED_STACK_ID) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800411 repositionDockedStackAfterRotation(mTmpRect2);
Jorim Jaggi737af722015-12-31 10:42:27 +0100412 snapDockedStackAfterRotation(mTmpRect2);
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700413 final int newDockSide = getDockSide(mTmpRect2);
414 if (oldDockSide != newDockSide) {
415 mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
416 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100417 }
418
Jorim Jaggieb1cb922016-04-27 20:37:45 -0700419 mBoundsAfterRotation.set(mTmpRect2);
Chong Zhang167bbfac2016-03-31 09:44:34 -0700420 return true;
421 }
422
423 void getBoundsForNewConfiguration(Rect outBounds) {
424 outBounds.set(mBoundsAfterRotation);
425 mBoundsAfterRotation.setEmpty();
Jorim Jaggi737af722015-12-31 10:42:27 +0100426 }
427
428 /**
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800429 * Some dock sides are not allowed by the policy. This method queries the policy and moves
430 * the docked stack around if needed.
431 *
432 * @param inOutBounds the bounds of the docked stack to adjust
433 */
434 private void repositionDockedStackAfterRotation(Rect inOutBounds) {
435 int dockSide = getDockSide(inOutBounds);
436 if (mService.mPolicy.isDockSideAllowed(dockSide)) {
437 return;
438 }
439 mDisplayContent.getLogicalDisplayRect(mTmpRect);
440 dockSide = DockedDividerUtils.invertDockSide(dockSide);
441 switch (dockSide) {
442 case DOCKED_LEFT:
443 int movement = inOutBounds.left;
444 inOutBounds.left -= movement;
445 inOutBounds.right -= movement;
446 break;
447 case DOCKED_RIGHT:
448 movement = mTmpRect.right - inOutBounds.right;
449 inOutBounds.left += movement;
450 inOutBounds.right += movement;
451 break;
452 case DOCKED_TOP:
453 movement = inOutBounds.top;
454 inOutBounds.top -= movement;
455 inOutBounds.bottom -= movement;
456 break;
457 case DOCKED_BOTTOM:
458 movement = mTmpRect.bottom - inOutBounds.bottom;
459 inOutBounds.top += movement;
460 inOutBounds.bottom += movement;
461 break;
462 }
463 }
464
465 /**
Jorim Jaggi737af722015-12-31 10:42:27 +0100466 * Snaps the bounds after rotation to the closest snap target for the docked stack.
467 */
468 private void snapDockedStackAfterRotation(Rect outBounds) {
469
470 // Calculate the current position.
471 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
472 final int dividerSize = mService.getDefaultDisplayContentLocked()
473 .getDockedDividerController().getContentWidth();
474 final int dockSide = getDockSide(outBounds);
475 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
476 dockSide, dividerSize);
477 final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
478 final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
479
480 // Snap the position to a target.
481 final int rotation = displayInfo.rotation;
482 final int orientation = mService.mCurConfiguration.orientation;
483 mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
484 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Jorim Jaggidf012d52016-01-15 22:40:13 -0800485 mService.mContext.getResources(), displayWidth, displayHeight,
Jorim Jaggi737af722015-12-31 10:42:27 +0100486 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds);
487 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
488
489 // Recalculate the bounds based on the position of the target.
490 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
491 outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
492 dividerSize);
493 }
494
Craig Mautner1bf2b872014-02-05 15:37:40 -0800495 boolean isAnimating() {
496 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
497 final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
498 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
499 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
500 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700501 final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
Jorim Jaggi5c80c412016-04-19 20:03:47 -0700502 if (winAnimator.isAnimationSet() || winAnimator.mWin.mAnimatingExit) {
Craig Mautner1bf2b872014-02-05 15:37:40 -0800503 return true;
504 }
505 }
506 }
507 }
508 return false;
509 }
510
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700511 void addTask(Task task, boolean toTop) {
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700512 addTask(task, toTop, task.showForAllUsers());
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700513 }
514
Craig Mautner00af9fe2013-03-25 09:13:41 -0700515 /**
516 * Put a Task in this stack. Used for adding and moving.
517 * @param task The task to add.
518 * @param toTop Whether to add it to the top or bottom.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700519 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700520 */
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700521 void addTask(Task task, boolean toTop, boolean showForAllUsers) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700522 positionTask(task, toTop ? mTasks.size() : 0, showForAllUsers);
523 }
524
525 void positionTask(Task task, int position, boolean showForAllUsers) {
526 final boolean canShowTask =
527 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
528 mTasks.remove(task);
529 int stackSize = mTasks.size();
530 int minPosition = 0;
531 int maxPosition = stackSize;
532
533 if (canShowTask) {
534 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700535 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700536 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700537 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700538 // Reset position based on minimum/maximum possible positions.
539 position = Math.min(Math.max(position, minPosition), maxPosition);
540
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800541 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM,
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700542 "positionTask: task=" + task + " position=" + position);
543 mTasks.add(position, task);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700544
Chong Zhangf66db432016-01-13 10:39:51 -0800545 // If we are moving the task across stacks, the scroll is no longer valid.
546 if (task.mStack != this) {
547 task.resetScrollLocked();
548 }
Craig Mautner967212c2013-04-13 21:10:58 -0700549 task.mStack = this;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700550 task.updateDisplayInfo(mDisplayContent);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700551 boolean toTop = position == mTasks.size() - 1;
raysb.kim00a27252014-11-11 08:38:21 +0900552 if (toTop) {
553 mDisplayContent.moveStack(this, true);
554 }
Robert Carr1b5ea722016-04-20 13:23:28 -0700555
556 if (StackId.windowsAreScaleable(mStackId)) {
557 // We force windows out of SCALING_MODE_FREEZE
558 // so that we can continue to animate them
559 // while a resize is pending.
560 forceWindowsScaleable(task, true);
561 } else {
562 forceWindowsScaleable(task, false);
563 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700564 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, position);
565 }
566
567 /** Calculate the minimum possible position for a task that can be shown to the user.
568 * The minimum position will be above all other tasks that can't be shown.
569 * @param minPosition The minimum position the caller is suggesting.
570 * We will start adjusting up from here.
571 * @param size The size of the current task list.
572 */
573 private int computeMinPosition(int minPosition, int size) {
574 while (minPosition < size) {
575 final Task tmpTask = mTasks.get(minPosition);
576 final boolean canShowTmpTask =
577 tmpTask.showForAllUsers()
578 || mService.isCurrentProfileLocked(tmpTask.mUserId);
579 if (canShowTmpTask) {
580 break;
581 }
582 minPosition++;
583 }
584 return minPosition;
585 }
586
587 /** Calculate the maximum possible position for a task that can't be shown to the user.
588 * The maximum position will be below all other tasks that can be shown.
589 * @param maxPosition The maximum position the caller is suggesting.
590 * We will start adjusting down from here.
591 */
592 private int computeMaxPosition(int maxPosition) {
593 while (maxPosition > 0) {
594 final Task tmpTask = mTasks.get(maxPosition - 1);
595 final boolean canShowTmpTask =
596 tmpTask.showForAllUsers()
597 || mService.isCurrentProfileLocked(tmpTask.mUserId);
598 if (!canShowTmpTask) {
599 break;
600 }
601 maxPosition--;
602 }
603 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800604 }
605
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800606 void moveTaskToTop(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800607 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToTop: task=" + task + " Callers="
Craig Mautnerf0ac5c82013-06-24 11:21:57 -0700608 + Debug.getCallers(6));
Craig Mautnerd9a22882013-03-16 15:00:36 -0700609 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800610 addTask(task, true);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700611 }
612
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800613 void moveTaskToBottom(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800614 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToBottom: task=" + task);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700615 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800616 addTask(task, false);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700617 }
618
Craig Mautner00af9fe2013-03-25 09:13:41 -0700619 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800620 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
621 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700622 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700623 */
Craig Mautnerde4ef022013-04-07 19:01:33 -0700624 void removeTask(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800625 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeTask: task=" + task);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700626 mTasks.remove(task);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800627 if (mDisplayContent != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800628 if (mTasks.isEmpty()) {
629 mDisplayContent.moveStack(this, false);
630 }
631 mDisplayContent.layoutNeeded = true;
Craig Mautner04a0ea62014-01-13 12:51:26 -0800632 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800633 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
634 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Craig Mautner83162a92015-01-26 14:43:30 -0800635 if (wtoken.mTask == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800636 wtoken.mIsExiting = false;
637 mExitingAppTokens.remove(appNdx);
638 }
639 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800640 }
641
Craig Mautnerdf88d732014-01-27 09:21:32 -0800642 void attachDisplayContent(DisplayContent displayContent) {
643 if (mDisplayContent != null) {
644 throw new IllegalStateException("attachDisplayContent: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800645 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800646
647 mDisplayContent = displayContent;
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100648 mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
649 "animation background stackId=" + mStackId);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700650
651 Rect bounds = null;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700652 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwale3797c222015-10-27 14:21:58 -0700653 if (mStackId == DOCKED_STACK_ID
Jorim Jaggi65002e12016-04-21 18:25:49 -0700654 || (dockedStack != null && StackId.isResizeableByDockedStack(mStackId)
655 && !dockedStack.isFullscreen())) {
Wale Ogunwale3797c222015-10-27 14:21:58 -0700656 // The existence of a docked stack affects the size of other static stack created since
Jorim Jaggi65002e12016-04-21 18:25:49 -0700657 // the docked stack occupies a dedicated region on screen, but only if the dock stack is
658 // not fullscreen. If it's fullscreen, it means that we are in the transition of
659 // dismissing it, so we must not resize this stack.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700660 bounds = new Rect();
661 displayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700662 mTmpRect2.setEmpty();
663 if (dockedStack != null) {
664 dockedStack.getRawBounds(mTmpRect2);
665 }
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800666 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700667 == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
668 getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100669 mDisplayContent.mDividerControllerLocked.getContentWidth(),
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700670 dockedOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700671 }
672
673 updateDisplayInfo(bounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700674 }
675
Wale Ogunwale961f4852016-02-01 20:25:54 -0800676 void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800677 if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
678 || mDisplayContent == null) {
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700679 outBounds.set(mBounds);
680 return;
681 }
682
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700683 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700684 if (dockedStack == null) {
685 // Not sure why you are calling this method when there is no docked stack...
686 throw new IllegalStateException(
687 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
688 }
Wale Ogunwale961f4852016-02-01 20:25:54 -0800689 if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700690 // The docked stack is being dismissed, but we caught before it finished being
691 // dismissed. In that case we want to treat it as if it is not occupying any space and
692 // let others occupy the whole display.
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -0800693 mDisplayContent.getLogicalDisplayRect(outBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700694 return;
695 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700696
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700697 final int dockedSide = dockedStack.getDockSide();
698 if (dockedSide == DOCKED_INVALID) {
699 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800700 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700701 outBounds.set(mBounds);
702 return;
703 }
704
705 mDisplayContent.getLogicalDisplayRect(mTmpRect);
706 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800707 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700708 getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100709 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700710
711 }
712
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700713 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700714 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700715 * @param displayRect The bounds of the display the docked stack is on.
716 * @param outBounds Output bounds that should be used for the stack.
717 * @param stackId Id of stack we are calculating the bounds for.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700718 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700719 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
720 * close to the side of the dock.
721 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700722 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800723 private void getStackDockedModeBounds(
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700724 Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
725 boolean dockOnTopOrLeft) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700726 final boolean dockedStack = stackId == DOCKED_STACK_ID;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700727 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700728
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700729 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700730 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800731 if (mService.mDockedStackCreateBounds != null) {
732 outBounds.set(mService.mDockedStackCreateBounds);
733 return;
734 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100735
736 // The initial bounds of the docked stack when it is created about half the screen space
737 // and its bounds can be adjusted after that. The bounds of all other stacks are
738 // adjusted to occupy whatever screen space the docked stack isn't occupying.
739 final DisplayInfo di = mDisplayContent.getDisplayInfo();
740 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
741 mTmpRect2);
742 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100743 di.logicalWidth,
744 di.logicalHeight,
745 dockDividerWidth,
746 mService.mCurConfiguration.orientation == ORIENTATION_PORTRAIT,
747 mTmpRect2).getMiddleTarget().position;
748
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700749 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700750 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100751 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700752 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100753 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700754 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700755 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700756 if (splitHorizontally) {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700757 outBounds.left = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700758 } else {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700759 outBounds.top = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700760 }
761 }
762 return;
763 }
764
765 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700766 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700767 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700768 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700769 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700770 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700771 }
772 } else {
773 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700774 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700775 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700776 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700777 }
778 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800779 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700780 }
781
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800782 void resetDockedStackToMiddle() {
783 if (mStackId != DOCKED_STACK_ID) {
784 throw new IllegalStateException("Not a docked stack=" + this);
785 }
786
787 mService.mDockedStackCreateBounds = null;
788
789 final Rect bounds = new Rect();
790 getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
791 mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
792 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
793 }
794
Craig Mautnerdc548482014-02-05 13:35:24 -0800795 void detachDisplay() {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800796 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700797
798 boolean doAnotherLayoutPass = false;
Craig Mautnerdc548482014-02-05 13:35:24 -0800799 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700800 final AppTokenList appWindowTokens = mTasks.get(taskNdx).mAppTokens;
801 for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
802 final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
803 for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
Filip Gruszczynskid66af6a2015-08-31 08:57:24 -0700804 // We are in the middle of changing the state of displays/stacks/tasks. We need
805 // to finish that, before we let layout interfere with it.
Filip Gruszczynski49b80af2015-09-24 09:04:26 -0700806 mService.removeWindowLocked(appWindows.get(winNdx));
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700807 doAnotherLayoutPass = true;
808 }
809 }
Craig Mautnerdc548482014-02-05 13:35:24 -0800810 }
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700811 if (doAnotherLayoutPass) {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700812 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700813 }
814
Craig Mautner00a66752015-03-23 14:00:47 -0700815 close();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700816 }
817
Craig Mautner05d29032013-05-03 13:40:13 -0700818 void resetAnimationBackgroundAnimator() {
819 mAnimationBackgroundAnimator = null;
820 mAnimationBackgroundSurface.hide();
821 }
822
Craig Mautner05d29032013-05-03 13:40:13 -0700823 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
824 int animLayer = winAnimator.mAnimLayer;
825 if (mAnimationBackgroundAnimator == null
826 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
827 mAnimationBackgroundAnimator = winAnimator;
828 animLayer = mService.adjustAnimationBackground(winAnimator);
829 mAnimationBackgroundSurface.show(animLayer - WindowManagerService.LAYER_OFFSET_DIM,
830 ((color >> 24) & 0xff) / 255f, 0);
831 }
832 }
833
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800834 void switchUser() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700835 int top = mTasks.size();
836 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
837 Task task = mTasks.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700838 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700839 mTasks.remove(taskNdx);
840 mTasks.add(task);
841 --top;
842 }
843 }
844 }
845
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800846 void close() {
Craig Mautner00a66752015-03-23 14:00:47 -0700847 if (mAnimationBackgroundSurface != null) {
848 mAnimationBackgroundSurface.destroySurface();
849 mAnimationBackgroundSurface = null;
850 }
Filip Gruszczynski26ed2652015-08-10 11:02:53 -0700851 mDisplayContent = null;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800852 }
853
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800854 /**
855 * Adjusts the stack bounds if the IME is visible.
856 *
857 * @param imeWin The IME window.
858 */
859 void setAdjustedForIme(WindowState imeWin) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800860 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -0700861 mImeGoingAway = false;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700862 if (!mAdjustedForIme) {
863 mAdjustedForIme = true;
864 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -0700865 mAdjustDividerAmount = 0f;
866 updateAdjustForIme(0f, 0f, true /* force */);
Jorim Jaggiff71d202016-04-14 13:12:36 -0700867 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700868 }
869
870 boolean isAdjustedForIme() {
871 return mAdjustedForIme || mImeGoingAway;
872 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700873
874 boolean isAnimatingForIme() {
875 return mImeWin != null && mImeWin.isAnimatingLw();
876 }
877
878 /**
879 * Update the stack's bounds (crop or position) according to the IME window's
880 * current position. When IME window is animated, the bottom stack is animated
881 * together to track the IME window's current position, and the top stack is
882 * cropped as necessary.
883 *
884 * @return true if a traversal should be performed after the adjustment.
885 */
Chong Zhangf347ab52016-04-18 21:02:01 -0700886 boolean updateAdjustForIme(float adjustAmount, float adjustDividerAmount, boolean force) {
887 if (adjustAmount != mAdjustImeAmount
888 || adjustDividerAmount != mAdjustDividerAmount || force) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700889 mAdjustImeAmount = adjustAmount;
Chong Zhangf347ab52016-04-18 21:02:01 -0700890 mAdjustDividerAmount = adjustDividerAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700891 updateAdjustedBounds();
892 return isVisibleForUserLocked();
893 } else {
894 return false;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700895 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800896 }
897
898 /**
899 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -0700900 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
901 * animations; otherwise, set flag and animates the window away together
902 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800903 */
Chong Zhangbaba7832016-03-24 10:21:26 -0700904 void resetAdjustedForIme(boolean adjustBoundsNow) {
905 if (adjustBoundsNow) {
906 mImeWin = null;
907 mAdjustedForIme = false;
908 mImeGoingAway = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700909 mAdjustImeAmount = 0f;
Chong Zhangf347ab52016-04-18 21:02:01 -0700910 mAdjustDividerAmount = 0f;
Chong Zhangbaba7832016-03-24 10:21:26 -0700911 updateAdjustedBounds();
Chong Zhang198afac2016-04-15 12:03:11 -0700912 mService.setResizeDimLayer(false, mStackId, 1.0f);
Chong Zhangbaba7832016-03-24 10:21:26 -0700913 } else {
914 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700915 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800916 }
917
918 /**
919 * Sets the amount how much we currently minimize our stack.
920 *
921 * @param minimizeAmount The amount, between 0 and 1.
922 * @return Whether the amount has changed and a layout is needed.
923 */
924 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
925 if (minimizeAmount != mMinimizeAmount) {
926 mMinimizeAmount = minimizeAmount;
927 updateAdjustedBounds();
928 return isVisibleForUserLocked();
929 } else {
930 return false;
931 }
932 }
933
Jorim Jaggi409635b2016-04-01 15:32:28 -0700934 boolean isAdjustedForMinimizedDock() {
935 return mMinimizeAmount != 0f;
936 }
937
Jorim Jaggiff71d202016-04-14 13:12:36 -0700938 /**
939 * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
940 * to the list of to be drawn windows the service is waiting for.
941 */
942 void beginImeAdjustAnimation() {
943 for (int j = mTasks.size() - 1; j >= 0; j--) {
944 final Task task = mTasks.get(j);
945 if (task.isVisibleForUser()) {
946 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
947 task.addWindowsWaitingForDrawnIfResizingChanged();
948 }
949 }
950 }
951
952 /**
953 * Resets the resizing state of all windows.
954 */
955 void endImeAdjustAnimation() {
956 for (int j = mTasks.size() - 1; j >= 0; j--) {
957 mTasks.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
958 }
959 }
960
Chong Zhang198afac2016-04-15 12:03:11 -0700961 int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
962 return displayContentRect.top + (int)
963 ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
964 }
965
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800966 private boolean adjustForIME(final WindowState imeWin) {
967 final int dockedSide = getDockSide();
968 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800969 if (imeWin == null || !dockedTopOrBottom) {
970 return false;
971 }
972
973 final Rect displayContentRect = mTmpRect;
974 final Rect contentBounds = mTmpRect2;
975
976 // Calculate the content bounds excluding the area occupied by IME
977 getDisplayContent().getContentRect(displayContentRect);
978 contentBounds.set(displayContentRect);
Jorim Jaggi5ac2ba22016-04-11 21:14:12 -0700979 int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -0700980
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800981 imeTop += imeWin.getGivenContentInsetsLw().top;
982 if (contentBounds.bottom > imeTop) {
983 contentBounds.bottom = imeTop;
984 }
985
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800986 final int yOffset = displayContentRect.bottom - contentBounds.bottom;
987
Chong Zhang198afac2016-04-15 12:03:11 -0700988 final int dividerWidth =
989 getDisplayContent().mDividerControllerLocked.getContentWidth();
990 final int dividerWidthInactive =
991 getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
992
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800993 if (dockedSide == DOCKED_TOP) {
994 // If this stack is docked on top, we make it smaller so the bottom stack is not
Chong Zhang198afac2016-04-15 12:03:11 -0700995 // occluded by IME. We shift its bottom up by the height of the IME, but
996 // leaves at least 30% of the top stack visible.
997 final int minTopStackBottom =
998 getMinTopStackBottom(displayContentRect, mBounds.bottom);
999 final int bottom = Math.max(
1000 mBounds.bottom - yOffset + dividerWidth - dividerWidthInactive,
1001 minTopStackBottom);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001002 mTmpAdjustedBounds.set(mBounds);
1003 mTmpAdjustedBounds.bottom =
1004 (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
1005 mFullyAdjustedImeBounds.set(mBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001006 } else {
Chong Zhangf347ab52016-04-18 21:02:01 -07001007 // When the stack is on bottom and has no focus, it's only adjusted for divider width.
1008 final int dividerWidthDelta = dividerWidthInactive - dividerWidth;
1009
1010 // When the stack is on bottom and has focus, it needs to be moved up so as to
1011 // not occluded by IME, and at the same time adjusted for divider width.
1012 // We try to move it up by the height of the IME window, but only to the extent
1013 // that leaves at least 30% of the top stack visible.
1014 // 'top' is where the top of bottom stack will move to in this case.
1015 final int topBeforeImeAdjust = mBounds.top - dividerWidth + dividerWidthInactive;
1016 final int minTopStackBottom =
1017 getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
1018 final int top = Math.max(
1019 mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
Chong Zhang198afac2016-04-15 12:03:11 -07001020
Jorim Jaggieb88d832016-04-13 20:17:43 -07001021 mTmpAdjustedBounds.set(mBounds);
Chong Zhangf347ab52016-04-18 21:02:01 -07001022 // Account for the adjustment for IME and divider width separately.
1023 // (top - topBeforeImeAdjust) is the amount of movement due to IME only,
1024 // and dividerWidthDelta is due to divider width change only.
1025 mTmpAdjustedBounds.top = mBounds.top +
1026 (int) (mAdjustImeAmount * (top - topBeforeImeAdjust) +
1027 mAdjustDividerAmount * dividerWidthDelta);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001028 mFullyAdjustedImeBounds.set(mBounds);
1029 mFullyAdjustedImeBounds.top = top;
1030 mFullyAdjustedImeBounds.bottom = top + mBounds.height();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001031 }
1032 return true;
1033 }
1034
1035 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
1036 final int dockSide = getDockSide();
1037 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
1038 return false;
1039 }
1040
1041 if (dockSide == DOCKED_TOP) {
1042 mService.getStableInsetsLocked(mTmpRect);
1043 int topInset = mTmpRect.top;
1044 mTmpAdjustedBounds.set(mBounds);
1045 mTmpAdjustedBounds.bottom =
1046 (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
1047 } else if (dockSide == DOCKED_LEFT) {
1048 mTmpAdjustedBounds.set(mBounds);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001049 final int width = mBounds.width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001050 mTmpAdjustedBounds.right =
1051 (int) (minimizeAmount * mDockedStackMinimizeThickness
1052 + (1 - minimizeAmount) * mBounds.right);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001053 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001054 } else if (dockSide == DOCKED_RIGHT) {
1055 mTmpAdjustedBounds.set(mBounds);
1056 mTmpAdjustedBounds.left =
1057 (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
1058 + (1 - minimizeAmount) * mBounds.left);
1059 }
1060 return true;
1061 }
1062
1063 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -08001064 * @return the distance in pixels how much the stack gets minimized from it's original size
1065 */
1066 int getMinimizeDistance() {
1067 final int dockSide = getDockSide();
1068 if (dockSide == DOCKED_INVALID) {
1069 return 0;
1070 }
1071
1072 if (dockSide == DOCKED_TOP) {
1073 mService.getStableInsetsLocked(mTmpRect);
1074 int topInset = mTmpRect.top;
1075 return mBounds.bottom - topInset;
1076 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
1077 return mBounds.width() - mDockedStackMinimizeThickness;
1078 } else {
1079 return 0;
1080 }
1081 }
1082
1083 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001084 * Updates the adjustment depending on it's current state.
1085 */
Jorim Jaggieb88d832016-04-13 20:17:43 -07001086 void updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001087 boolean adjust = false;
1088 if (mMinimizeAmount != 0f) {
1089 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1090 } else if (mAdjustedForIme) {
1091 adjust = adjustForIME(mImeWin);
1092 }
1093 if (!adjust) {
1094 mTmpAdjustedBounds.setEmpty();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001095 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001096 setAdjustedBounds(mTmpAdjustedBounds);
Chong Zhang198afac2016-04-15 12:03:11 -07001097
Chong Zhangf347ab52016-04-18 21:02:01 -07001098 final boolean isImeTarget = (mService.getImeTargetStackLocked() == this);
1099 if (mAdjustedForIme && adjust && !isImeTarget) {
1100 final float alpha = Math.max(mAdjustImeAmount, mAdjustDividerAmount)
1101 * IME_ADJUST_DIM_AMOUNT;
Chong Zhang198afac2016-04-15 12:03:11 -07001102 mService.setResizeDimLayer(true, mStackId, alpha);
1103 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001104 }
1105
1106 boolean isAdjustedForMinimizedDockedStack() {
1107 return mMinimizeAmount != 0f;
1108 }
1109
Craig Mautner00af9fe2013-03-25 09:13:41 -07001110 public void dump(String prefix, PrintWriter pw) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001111 pw.println(prefix + "mStackId=" + mStackId);
1112 pw.println(prefix + "mDeferDetach=" + mDeferDetach);
1113 pw.println(prefix + "mFullscreen=" + mFullscreen);
1114 pw.println(prefix + "mBounds=" + mBounds.toShortString());
Jorim Jaggiaf558e12016-04-27 22:56:56 -07001115 if (mMinimizeAmount != 0f) {
1116 pw.println(prefix + "mMinimizeAmout=" + mMinimizeAmount);
1117 }
1118 if (mAdjustedForIme) {
1119 pw.println(prefix + "mAdjustedForIme=true");
1120 pw.println(prefix + "mAdjustImeAmount=" + mAdjustImeAmount);
1121 pw.println(prefix + "mAdjustDividerAmount=" + mAdjustDividerAmount);
1122 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001123 if (!mAdjustedBounds.isEmpty()) {
1124 pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
1125 }
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001126 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; taskNdx--) {
1127 mTasks.get(taskNdx).dump(prefix + " ", pw);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001128 }
Craig Mautner05d29032013-05-03 13:40:13 -07001129 if (mAnimationBackgroundSurface.isDimming()) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001130 pw.println(prefix + "mWindowAnimationBackgroundSurface:");
Craig Mautner05d29032013-05-03 13:40:13 -07001131 mAnimationBackgroundSurface.printTo(prefix + " ", pw);
1132 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001133 if (!mExitingAppTokens.isEmpty()) {
1134 pw.println();
1135 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001136 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001137 WindowToken token = mExitingAppTokens.get(i);
1138 pw.print(" Exiting App #"); pw.print(i);
1139 pw.print(' '); pw.print(token);
1140 pw.println(':');
1141 token.dump(pw, " ");
1142 }
1143 }
Craig Mautner00af9fe2013-03-25 09:13:41 -07001144 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001145
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001146 /** Fullscreen status of the stack without adjusting for other factors in the system like
1147 * visibility of docked stack.
1148 * Most callers should be using {@link #isFullscreen} as it take into consideration other
1149 * system factors. */
1150 boolean getRawFullscreen() {
1151 return mFullscreen;
1152 }
1153
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001154 @Override
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001155 public boolean isFullscreen() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001156 if (useCurrentBounds()) {
1157 return mFullscreen;
1158 }
1159 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
1160 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
1161 // system.
1162 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001163 }
1164
1165 @Override
1166 public DisplayInfo getDisplayInfo() {
1167 return mDisplayContent.getDisplayInfo();
1168 }
1169
1170 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001171 public String toString() {
1172 return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
1173 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001174
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001175 @Override
1176 public String toShortString() {
1177 return "Stack=" + mStackId;
1178 }
1179
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001180 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001181 * For docked workspace (or workspace that's side-by-side to the docked), provides
1182 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001183 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001184 int getDockSide() {
Jorim Jaggi737af722015-12-31 10:42:27 +01001185 return getDockSide(mBounds);
1186 }
1187
1188 int getDockSide(Rect bounds) {
Chong Zhangc806d902015-11-30 09:44:27 -08001189 if (mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId)) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001190 return DOCKED_INVALID;
1191 }
1192 if (mDisplayContent == null) {
1193 return DOCKED_INVALID;
1194 }
1195 mDisplayContent.getLogicalDisplayRect(mTmpRect);
1196 final int orientation = mService.mCurConfiguration.orientation;
1197 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
1198 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi067e8172016-02-03 18:24:12 -08001199 if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001200 return DOCKED_TOP;
1201 } else {
1202 return DOCKED_BOTTOM;
1203 }
1204 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1205 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi067e8172016-02-03 18:24:12 -08001206 if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001207 return DOCKED_LEFT;
1208 } else {
1209 return DOCKED_RIGHT;
1210 }
1211 } else {
1212 return DOCKED_INVALID;
1213 }
1214 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001215
1216 boolean isVisibleLocked() {
Jorim Jaggi7998e482016-02-12 18:47:06 -08001217 final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded()
1218 && !mService.mAnimator.mKeyguardGoingAway;
Chong Zhang75b37202015-12-04 14:16:36 -08001219 if (keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -08001220 // The keyguard is showing and the stack shouldn't show on top of the keyguard.
Wale Ogunwale961f4852016-02-01 20:25:54 -08001221 return false;
Chong Zhang75b37202015-12-04 14:16:36 -08001222 }
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -08001223
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001224 for (int i = mTasks.size() - 1; i >= 0; i--) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001225 final Task task = mTasks.get(i);
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001226 for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
1227 if (!task.mAppTokens.get(j).hidden) {
1228 return true;
1229 }
1230 }
1231 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001232
1233 return false;
1234 }
1235
1236 /**
1237 * @return true if a the stack is visible for the current in user, ignoring any other visibility
1238 * aspects, and false otherwise
1239 */
1240 boolean isVisibleForUserLocked() {
1241 for (int i = mTasks.size() - 1; i >= 0; i--) {
1242 final Task task = mTasks.get(i);
1243 if (task.isVisibleForUser()) {
1244 return true;
1245 }
1246 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001247 return false;
1248 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001249
Wale Ogunwalece144522016-02-05 22:51:01 -08001250 boolean isDragResizing() {
1251 return mDragResizing;
1252 }
1253
Jorim Jaggiff71d202016-04-14 13:12:36 -07001254 void setDragResizingLocked(boolean resizing) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08001255 if (mDragResizing == resizing) {
1256 return;
1257 }
1258 mDragResizing = resizing;
1259 for (int i = mTasks.size() - 1; i >= 0 ; i--) {
1260 mTasks.get(i).resetDragResizingChangeReported();
1261 }
1262 }
1263
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001264 @Override // AnimatesBounds
1265 public boolean setSize(Rect bounds) {
1266 synchronized (mService.mWindowMap) {
1267 if (mDisplayContent == null) {
1268 return false;
1269 }
1270 }
1271 try {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001272 mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false, -1);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001273 } catch (RemoteException e) {
1274 }
1275 return true;
1276 }
1277
Robert Carr0d00c2e2016-02-29 17:45:02 -08001278 public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
1279 synchronized (mService.mWindowMap) {
1280 if (mDisplayContent == null) {
1281 return false;
1282 }
1283 if (mStackId != PINNED_STACK_ID) {
1284 Slog.w(TAG_WM, "Attempt to use pinned stack resize animation helper on"
1285 + "non pinned stack");
1286 return false;
1287 }
1288 }
1289 try {
1290 mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
1291 } catch (RemoteException e) {
1292 // I don't believe you.
1293 }
1294 return true;
1295 }
1296
Robert Carr1b5ea722016-04-20 13:23:28 -07001297 void forceWindowsScaleable(Task task, boolean force) {
Robert Carr1ca6a332016-04-11 18:00:43 -07001298 SurfaceControl.openTransaction();
1299 try {
Robert Carr1b5ea722016-04-20 13:23:28 -07001300 final ArrayList<AppWindowToken> activities = task.mAppTokens;
1301 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1302 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
1303 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
1304 final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
1305 if (winAnimator == null || !winAnimator.hasSurface()) {
1306 continue;
Robert Carr1ca6a332016-04-11 18:00:43 -07001307 }
Robert Carr1b5ea722016-04-20 13:23:28 -07001308 winAnimator.mSurfaceController.forceScaleableInTransaction(force);
Robert Carr1ca6a332016-04-11 18:00:43 -07001309 }
1310 }
1311 } finally {
1312 SurfaceControl.closeTransaction();
1313 }
1314 }
1315
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001316 @Override // AnimatesBounds
Wale Ogunwalece144522016-02-05 22:51:01 -08001317 public void onAnimationStart() {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001318 synchronized (mService.mWindowMap) {
Robert Carr0d00c2e2016-02-29 17:45:02 -08001319 mFreezeMovementAnimations = true;
Robert Carr1ca6a332016-04-11 18:00:43 -07001320 mBoundsAnimating = true;
Wale Ogunwalece144522016-02-05 22:51:01 -08001321 }
1322 }
1323
1324 @Override // AnimatesBounds
1325 public void onAnimationEnd() {
1326 synchronized (mService.mWindowMap) {
Robert Carr0d00c2e2016-02-29 17:45:02 -08001327 mFreezeMovementAnimations = false;
Robert Carr1ca6a332016-04-11 18:00:43 -07001328 mBoundsAnimating = false;
Wale Ogunwalece144522016-02-05 22:51:01 -08001329 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001330 }
Wale Ogunwale480dca02016-02-06 13:58:29 -08001331 if (mStackId == PINNED_STACK_ID) {
1332 try {
1333 mService.mActivityManager.notifyPinnedStackAnimationEnded();
1334 } catch (RemoteException e) {
1335 // I don't believe you...
1336 }
1337 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001338 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001339
1340 @Override
1341 public void moveToFullscreen() {
1342 try {
1343 mService.mActivityManager.moveTasksToFullscreenStack(mStackId, true);
1344 } catch (RemoteException e) {
1345 e.printStackTrace();
1346 }
1347 }
1348
1349 @Override
1350 public void getFullScreenBounds(Rect bounds) {
1351 getDisplayContent().getContentRect(bounds);
1352 }
Robert Carr0d00c2e2016-02-29 17:45:02 -08001353
1354 public boolean getFreezeMovementAnimations() {
1355 return mFreezeMovementAnimations;
1356 }
1357
1358 public boolean getForceScaleToCrop() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001359 return mBoundsAnimating;
1360 }
1361
1362 public boolean getBoundsAnimating() {
1363 return mBoundsAnimating;
Robert Carr0d00c2e2016-02-29 17:45:02 -08001364 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001365}