blob: 1fd2b1f2dfa3ec70911a8aff884541662c3773e2 [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;
21import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
22import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
23import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
24import static android.view.WindowManager.DOCKED_BOTTOM;
25import static android.view.WindowManager.DOCKED_INVALID;
26import static android.view.WindowManager.DOCKED_LEFT;
27import static android.view.WindowManager.DOCKED_RIGHT;
28import static android.view.WindowManager.DOCKED_TOP;
Jorim Jaggiff71d202016-04-14 13:12:36 -070029import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
Jorim Jaggi2917dc42016-04-11 11:39:13 -070030import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
31import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
32import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
33
Wale Ogunwale3797c222015-10-27 14:21:58 -070034import android.app.ActivityManager.StackId;
Wale Ogunwale60454db2015-01-23 16:05:07 -080035import android.content.res.Configuration;
Craig Mautner05d29032013-05-03 13:40:13 -070036import android.graphics.Rect;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070037import android.os.Debug;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080038import android.os.RemoteException;
Craig Mautner2c2549c2013-11-12 08:31:15 -080039import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070040import android.util.Slog;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070041import android.util.SparseArray;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070042import android.view.DisplayInfo;
Wale Ogunwale94744212015-09-21 19:01:47 -070043import android.view.Surface;
Jorim Jaggieb88d832016-04-13 20:17:43 -070044import android.view.animation.PathInterpolator;
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
114 // Display rotation as of the last time the display information was updated for this stack.
115 private int mLastUpdateDisplayInfoRotation = -1;
116 // Display rotation as of the last time the configuration was updated for this stack.
117 private int mLastConfigChangedRotation = -1;
Craig Mautner95da1082014-02-24 17:54:35 -0800118
Wale Ogunwalece144522016-02-05 22:51:01 -0800119 // Whether the stack and all its tasks is currently being drag-resized
120 private boolean mDragResizing;
121
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800122 private final Rect mLastContentBounds = new Rect();
123 private final Rect mTmpAdjustedBounds = new Rect();
124 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700125 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800126 private WindowState mImeWin;
127 private float mMinimizeAmount;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700128 private float mAdjustImeAmount;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800129 private final int mDockedStackMinimizeThickness;
130
Robert Carr1ca6a332016-04-11 18:00:43 -0700131 // If this is true, we are in the bounds animating mode.
132 // The task will be down or upscaled to perfectly fit the
133 // region it would have been cropped to. We may also avoid
134 // certain logic we would otherwise apply while resizing,
135 // while resizing in the bounds animating mode.
136 private boolean mBoundsAnimating = false;
Robert Carr0d00c2e2016-02-29 17:45:02 -0800137 // By default, movement animations are applied to all
138 // window movement. If this is true, animations will not
139 // be applied within this stack. This is useful for example
140 // if the windows are moving as the result of a stack animation,
141 // in which case a second window animation would cause jitter.
142 private boolean mFreezeMovementAnimations = false;
143
Chong Zhang167bbfac2016-03-31 09:44:34 -0700144 // Temporary storage for the new bounds that should be used after the configuration change.
145 // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
146 private final Rect mBoundsAfterRotation = new Rect();
147
Craig Mautnerdf88d732014-01-27 09:21:32 -0800148 TaskStack(WindowManagerService service, int stackId) {
Craig Mautner05d29032013-05-03 13:40:13 -0700149 mService = service;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800150 mStackId = stackId;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800151 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
152 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700153 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800154 }
155
156 DisplayContent getDisplayContent() {
157 return mDisplayContent;
158 }
159
Craig Mautnerd9a22882013-03-16 15:00:36 -0700160 ArrayList<Task> getTasks() {
161 return mTasks;
162 }
163
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700164 /**
165 * Set the bounds of the stack and its containing tasks.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700166 * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700167 * @param configs Configuration for individual tasks, keyed by task id.
168 * @param taskBounds Bounds for individual tasks, keyed by task id.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700169 * @return True if the stack bounds was changed.
170 * */
Wale Ogunwalea6e902e2015-09-21 18:37:15 -0700171 boolean setBounds(
Jorim Jaggidc249c42015-12-15 14:57:31 -0800172 Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
173 SparseArray<Rect> taskTempInsetBounds) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500174 setBounds(stackBounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700175
176 // Update bounds of containing tasks.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700177 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
178 final Task task = mTasks.get(taskNdx);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700179 Configuration config = configs.get(task.mTaskId);
180 if (config != null) {
181 Rect bounds = taskBounds.get(task.mTaskId);
Chong Zhang2a88fc32016-01-11 17:14:24 -0800182 if (task.isTwoFingerScrollMode()) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800183 // This is a non-resizeable task that's docked (or side-by-side to the docked
184 // stack). It might have been scrolled previously, and after the stack resizing,
185 // it might no longer fully cover the stack area.
186 // Save the old bounds and re-apply the scroll. This adjusts the bounds to
187 // fit the new stack bounds.
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100188 task.resizeLocked(bounds, config, false /* forced */);
Chong Zhangf66db432016-01-13 10:39:51 -0800189 task.getBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800190 task.scrollLocked(mTmpRect);
191 } else {
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100192 task.resizeLocked(bounds, config, false /* forced */);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800193 task.setTempInsetBounds(
194 taskTempInsetBounds != null ? taskTempInsetBounds.get(task.mTaskId)
195 : null);
Chong Zhangb15758a2015-11-17 12:12:03 -0800196 }
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700197 } else {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800198 Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700199 }
200 }
201 return true;
202 }
203
Jorim Jaggi0429f352015-12-22 16:29:16 +0100204 void prepareFreezingTaskBounds() {
205 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
206 final Task task = mTasks.get(taskNdx);
207 task.prepareFreezingBounds();
208 }
209 }
210
Wale Ogunwaleb4ec0a32015-12-14 10:31:43 -0800211 boolean isFullscreenBounds(Rect bounds) {
212 if (mDisplayContent == null || bounds == null) {
213 return true;
214 }
215 mDisplayContent.getLogicalDisplayRect(mTmpRect);
216 return mTmpRect.equals(bounds);
217 }
218
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800219 /**
220 * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
221 * the normal task bounds.
222 *
223 * @param bounds The adjusted bounds.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800224 */
Jorim Jaggieb88d832016-04-13 20:17:43 -0700225 private void setAdjustedBounds(Rect bounds) {
226 if (mAdjustedBounds.equals(bounds) && !isAnimatingForIme()) {
227 return;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800228 }
229
230 mAdjustedBounds.set(bounds);
231 final boolean adjusted = !mAdjustedBounds.isEmpty();
Jorim Jaggieb88d832016-04-13 20:17:43 -0700232 Rect insetBounds = null;
233 if (adjusted && isAdjustedForMinimizedDock()) {
234 insetBounds = mBounds;
235 } else if (adjusted && isAdjustedForIme()) {
236 if (mImeGoingAway) {
237 insetBounds = mBounds;
238 } else {
239 insetBounds = mFullyAdjustedImeBounds;
240 }
241 }
242 alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds, insetBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800243 mDisplayContent.layoutNeeded = true;
244 }
245
246 private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
Chong Zhangb816b862016-01-25 12:01:12 -0800247 if (mFullscreen) {
248 return;
249 }
250 // Update bounds of containing tasks.
251 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
252 final Task task = mTasks.get(taskNdx);
253 if (task.isTwoFingerScrollMode()) {
254 // If we're scrolling we don't care about your bounds or configs,
255 // they should be null as if we were in fullscreen.
256 task.resizeLocked(null, null, false /* forced */);
257 task.getBounds(mTmpRect2);
258 task.scrollLocked(mTmpRect2);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800259 } else if (task.isResizeable() && task.mOverrideConfig != Configuration.EMPTY) {
Chong Zhangb816b862016-01-25 12:01:12 -0800260 task.getBounds(mTmpRect2);
Chong Zhang198afac2016-04-15 12:03:11 -0700261 if (mAdjustedForIme && getDockSide() == DOCKED_TOP) {
262 int offsetY = adjustedBounds.bottom - mTmpRect2.bottom;
263 mTmpRect2.offset(0, offsetY);
264 } else {
265 mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
266 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800267 task.setTempInsetBounds(tempInsetBounds);
Chong Zhangb816b862016-01-25 12:01:12 -0800268 task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */);
269 }
270 }
271 }
272
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700273 private boolean setBounds(Rect bounds) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800274 boolean oldFullscreen = mFullscreen;
Wale Ogunwale94744212015-09-21 19:01:47 -0700275 int rotation = Surface.ROTATION_0;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700276 int density = DENSITY_DPI_UNDEFINED;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800277 if (mDisplayContent != null) {
278 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwale94744212015-09-21 19:01:47 -0700279 rotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700280 density = mDisplayContent.getDisplayInfo().logicalDensityDpi;
Jorim Jaggi067e8172016-02-03 18:24:12 -0800281 mFullscreen = bounds == null;
282 if (mFullscreen) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800283 bounds = mTmpRect;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800284 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800285 }
286
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800287 if (bounds == null) {
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800288 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800289 return false;
290 }
Wale Ogunwale94744212015-09-21 19:01:47 -0700291 if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800292 return false;
293 }
294
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700295 if (mDisplayContent != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800296 mDisplayContent.mDimLayerController.updateDimLayer(this);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700297 mAnimationBackgroundSurface.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700298 }
299
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800300 mBounds.set(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700301 mRotation = rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700302 mDensity = density;
Chong Zhangb816b862016-01-25 12:01:12 -0800303
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800304 updateAdjustedBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800305
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800306 return true;
307 }
308
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700309 /** Bounds of the stack without adjusting for other factors in the system like visibility
310 * of docked stack.
311 * Most callers should be using {@link #getBounds} as it take into consideration other system
312 * factors. */
313 void getRawBounds(Rect out) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800314 out.set(mBounds);
315 }
316
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700317 /** Return true if the current bound can get outputted to the rest of the system as-is. */
318 private boolean useCurrentBounds() {
319 if (mFullscreen
Wale Ogunwale3797c222015-10-27 14:21:58 -0700320 || !StackId.isResizeableByDockedStack(mStackId)
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700321 || mDisplayContent == null
322 || mDisplayContent.getDockedStackLocked() != null) {
323 return true;
324 }
325 return false;
326 }
327
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700328 public void getBounds(Rect out) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700329 if (useCurrentBounds()) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800330 // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
331 // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
332 // stack is visible since it is already what we want to represent to the rest of the
333 // system.
334 if (!mAdjustedBounds.isEmpty()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800335 out.set(mAdjustedBounds);
336 } else {
337 out.set(mBounds);
338 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700339 return;
340 }
341
342 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
343 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
344 // system.
345 mDisplayContent.getLogicalDisplayRect(out);
346 }
347
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800348 /** Bounds of the stack with other system factors taken into consideration. */
349 @Override
350 public void getDimBounds(Rect out) {
351 getBounds(out);
352 }
353
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700354 void updateDisplayInfo(Rect bounds) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800355 if (mDisplayContent == null) {
356 return;
357 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100358
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800359 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
360 mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
361 }
362 if (bounds != null) {
363 setBounds(bounds);
364 return;
365 } else if (mFullscreen) {
366 setBounds(null);
367 return;
368 }
369
370 mTmpRect2.set(mBounds);
371 final int newRotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700372 final int newDensity = mDisplayContent.getDisplayInfo().logicalDensityDpi;
373 if (mRotation == newRotation && mDensity == newDensity) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800374 setBounds(mTmpRect2);
375 } else {
376 mLastUpdateDisplayInfoRotation = newRotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700377 updateBoundsAfterConfigChange(true);
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800378 }
379 }
380
Chong Zhang167bbfac2016-03-31 09:44:34 -0700381 boolean onConfigurationChanged() {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800382 mLastConfigChangedRotation = getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700383 return updateBoundsAfterConfigChange(false);
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800384 }
385
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700386 boolean updateBoundsAfterConfigChange(boolean scheduleResize) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800387 if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) {
388 // We wait for the rotation values after configuration change and display info. update
389 // to be equal before updating the bounds due to rotation change otherwise things might
390 // get out of alignment...
Chong Zhang167bbfac2016-03-31 09:44:34 -0700391 return false;
Filip Gruszczynskidce2d162016-01-12 15:40:13 -0800392 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800393
Jorim Jaggi737af722015-12-31 10:42:27 +0100394 final int newRotation = getDisplayInfo().rotation;
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700395 final int newDensity = getDisplayInfo().logicalDensityDpi;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800396
Jorim Jaggi11c62e12016-04-05 20:41:21 -0700397 if (mRotation == newRotation && mDensity == newDensity) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800398 // Nothing to do here if the rotation didn't change
Chong Zhang167bbfac2016-03-31 09:44:34 -0700399 return false;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800400 }
401
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700402 final int oldDockSide = mStackId == DOCKED_STACK_ID ? getDockSide() : DOCKED_INVALID;
Jorim Jaggi737af722015-12-31 10:42:27 +0100403 mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
404 if (mStackId == DOCKED_STACK_ID) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800405 repositionDockedStackAfterRotation(mTmpRect2);
Jorim Jaggi737af722015-12-31 10:42:27 +0100406 snapDockedStackAfterRotation(mTmpRect2);
Jorim Jaggi2917dc42016-04-11 11:39:13 -0700407 final int newDockSide = getDockSide(mTmpRect2);
408 if (oldDockSide != newDockSide) {
409 mDisplayContent.getDockedDividerController().notifyDockSideChanged(newDockSide);
410 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100411 }
412
Chong Zhang167bbfac2016-03-31 09:44:34 -0700413 if (scheduleResize) {
414 // Post message to inform activity manager of the bounds change simulating
415 // a one-way call. We do this to prevent a deadlock between window manager
416 // lock and activity manager lock been held.
417 mService.mH.obtainMessage(RESIZE_STACK, mStackId,
418 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
419 } else {
420 mBoundsAfterRotation.set(mTmpRect2);
421 }
422
423 return true;
424 }
425
426 void getBoundsForNewConfiguration(Rect outBounds) {
427 outBounds.set(mBoundsAfterRotation);
428 mBoundsAfterRotation.setEmpty();
Jorim Jaggi737af722015-12-31 10:42:27 +0100429 }
430
431 /**
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800432 * Some dock sides are not allowed by the policy. This method queries the policy and moves
433 * the docked stack around if needed.
434 *
435 * @param inOutBounds the bounds of the docked stack to adjust
436 */
437 private void repositionDockedStackAfterRotation(Rect inOutBounds) {
438 int dockSide = getDockSide(inOutBounds);
439 if (mService.mPolicy.isDockSideAllowed(dockSide)) {
440 return;
441 }
442 mDisplayContent.getLogicalDisplayRect(mTmpRect);
443 dockSide = DockedDividerUtils.invertDockSide(dockSide);
444 switch (dockSide) {
445 case DOCKED_LEFT:
446 int movement = inOutBounds.left;
447 inOutBounds.left -= movement;
448 inOutBounds.right -= movement;
449 break;
450 case DOCKED_RIGHT:
451 movement = mTmpRect.right - inOutBounds.right;
452 inOutBounds.left += movement;
453 inOutBounds.right += movement;
454 break;
455 case DOCKED_TOP:
456 movement = inOutBounds.top;
457 inOutBounds.top -= movement;
458 inOutBounds.bottom -= movement;
459 break;
460 case DOCKED_BOTTOM:
461 movement = mTmpRect.bottom - inOutBounds.bottom;
462 inOutBounds.top += movement;
463 inOutBounds.bottom += movement;
464 break;
465 }
466 }
467
468 /**
Jorim Jaggi737af722015-12-31 10:42:27 +0100469 * Snaps the bounds after rotation to the closest snap target for the docked stack.
470 */
471 private void snapDockedStackAfterRotation(Rect outBounds) {
472
473 // Calculate the current position.
474 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
475 final int dividerSize = mService.getDefaultDisplayContentLocked()
476 .getDockedDividerController().getContentWidth();
477 final int dockSide = getDockSide(outBounds);
478 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
479 dockSide, dividerSize);
480 final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
481 final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
482
483 // Snap the position to a target.
484 final int rotation = displayInfo.rotation;
485 final int orientation = mService.mCurConfiguration.orientation;
486 mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
487 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Jorim Jaggidf012d52016-01-15 22:40:13 -0800488 mService.mContext.getResources(), displayWidth, displayHeight,
Jorim Jaggi737af722015-12-31 10:42:27 +0100489 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds);
490 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
491
492 // Recalculate the bounds based on the position of the target.
493 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
494 outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
495 dividerSize);
496 }
497
Craig Mautner1bf2b872014-02-05 15:37:40 -0800498 boolean isAnimating() {
499 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
500 final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
501 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
502 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
503 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700504 final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800505 if (winAnimator.isAnimating() || winAnimator.mWin.mAnimatingExit) {
Craig Mautner1bf2b872014-02-05 15:37:40 -0800506 return true;
507 }
508 }
509 }
510 }
511 return false;
512 }
513
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700514 void addTask(Task task, boolean toTop) {
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700515 addTask(task, toTop, task.showForAllUsers());
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700516 }
517
Craig Mautner00af9fe2013-03-25 09:13:41 -0700518 /**
519 * Put a Task in this stack. Used for adding and moving.
520 * @param task The task to add.
521 * @param toTop Whether to add it to the top or bottom.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700522 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700523 */
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700524 void addTask(Task task, boolean toTop, boolean showForAllUsers) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700525 positionTask(task, toTop ? mTasks.size() : 0, showForAllUsers);
526 }
527
528 void positionTask(Task task, int position, boolean showForAllUsers) {
529 final boolean canShowTask =
530 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
531 mTasks.remove(task);
532 int stackSize = mTasks.size();
533 int minPosition = 0;
534 int maxPosition = stackSize;
535
536 if (canShowTask) {
537 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700538 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700539 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700540 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700541 // Reset position based on minimum/maximum possible positions.
542 position = Math.min(Math.max(position, minPosition), maxPosition);
543
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800544 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM,
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700545 "positionTask: task=" + task + " position=" + position);
546 mTasks.add(position, task);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700547
Chong Zhangf66db432016-01-13 10:39:51 -0800548 // If we are moving the task across stacks, the scroll is no longer valid.
549 if (task.mStack != this) {
550 task.resetScrollLocked();
551 }
Craig Mautner967212c2013-04-13 21:10:58 -0700552 task.mStack = this;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700553 task.updateDisplayInfo(mDisplayContent);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700554 boolean toTop = position == mTasks.size() - 1;
raysb.kim00a27252014-11-11 08:38:21 +0900555 if (toTop) {
556 mDisplayContent.moveStack(this, true);
557 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700558 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, position);
559 }
560
561 /** Calculate the minimum possible position for a task that can be shown to the user.
562 * The minimum position will be above all other tasks that can't be shown.
563 * @param minPosition The minimum position the caller is suggesting.
564 * We will start adjusting up from here.
565 * @param size The size of the current task list.
566 */
567 private int computeMinPosition(int minPosition, int size) {
568 while (minPosition < size) {
569 final Task tmpTask = mTasks.get(minPosition);
570 final boolean canShowTmpTask =
571 tmpTask.showForAllUsers()
572 || mService.isCurrentProfileLocked(tmpTask.mUserId);
573 if (canShowTmpTask) {
574 break;
575 }
576 minPosition++;
577 }
578 return minPosition;
579 }
580
581 /** Calculate the maximum possible position for a task that can't be shown to the user.
582 * The maximum position will be below all other tasks that can be shown.
583 * @param maxPosition The maximum position the caller is suggesting.
584 * We will start adjusting down from here.
585 */
586 private int computeMaxPosition(int maxPosition) {
587 while (maxPosition > 0) {
588 final Task tmpTask = mTasks.get(maxPosition - 1);
589 final boolean canShowTmpTask =
590 tmpTask.showForAllUsers()
591 || mService.isCurrentProfileLocked(tmpTask.mUserId);
592 if (!canShowTmpTask) {
593 break;
594 }
595 maxPosition--;
596 }
597 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800598 }
599
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800600 void moveTaskToTop(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800601 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToTop: task=" + task + " Callers="
Craig Mautnerf0ac5c82013-06-24 11:21:57 -0700602 + Debug.getCallers(6));
Craig Mautnerd9a22882013-03-16 15:00:36 -0700603 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800604 addTask(task, true);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700605 }
606
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800607 void moveTaskToBottom(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800608 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToBottom: task=" + task);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700609 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800610 addTask(task, false);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700611 }
612
Craig Mautner00af9fe2013-03-25 09:13:41 -0700613 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800614 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
615 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700616 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700617 */
Craig Mautnerde4ef022013-04-07 19:01:33 -0700618 void removeTask(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800619 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeTask: task=" + task);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700620 mTasks.remove(task);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800621 if (mDisplayContent != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800622 if (mTasks.isEmpty()) {
623 mDisplayContent.moveStack(this, false);
624 }
625 mDisplayContent.layoutNeeded = true;
Craig Mautner04a0ea62014-01-13 12:51:26 -0800626 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800627 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
628 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Craig Mautner83162a92015-01-26 14:43:30 -0800629 if (wtoken.mTask == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800630 wtoken.mIsExiting = false;
631 mExitingAppTokens.remove(appNdx);
632 }
633 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800634 }
635
Craig Mautnerdf88d732014-01-27 09:21:32 -0800636 void attachDisplayContent(DisplayContent displayContent) {
637 if (mDisplayContent != null) {
638 throw new IllegalStateException("attachDisplayContent: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800639 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800640
641 mDisplayContent = displayContent;
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100642 mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
643 "animation background stackId=" + mStackId);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700644
645 Rect bounds = null;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700646 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwale3797c222015-10-27 14:21:58 -0700647 if (mStackId == DOCKED_STACK_ID
648 || (dockedStack != null && StackId.isResizeableByDockedStack(mStackId))) {
649 // The existence of a docked stack affects the size of other static stack created since
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700650 // the docked stack occupies a dedicated region on screen.
651 bounds = new Rect();
652 displayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700653 mTmpRect2.setEmpty();
654 if (dockedStack != null) {
655 dockedStack.getRawBounds(mTmpRect2);
656 }
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800657 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700658 == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
659 getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100660 mDisplayContent.mDividerControllerLocked.getContentWidth(),
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700661 dockedOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700662 }
663
664 updateDisplayInfo(bounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700665 }
666
Wale Ogunwale961f4852016-02-01 20:25:54 -0800667 void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800668 if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
669 || mDisplayContent == null) {
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700670 outBounds.set(mBounds);
671 return;
672 }
673
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700674 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700675 if (dockedStack == null) {
676 // Not sure why you are calling this method when there is no docked stack...
677 throw new IllegalStateException(
678 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
679 }
Wale Ogunwale961f4852016-02-01 20:25:54 -0800680 if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700681 // The docked stack is being dismissed, but we caught before it finished being
682 // dismissed. In that case we want to treat it as if it is not occupying any space and
683 // let others occupy the whole display.
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -0800684 mDisplayContent.getLogicalDisplayRect(outBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700685 return;
686 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700687
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700688 final int dockedSide = dockedStack.getDockSide();
689 if (dockedSide == DOCKED_INVALID) {
690 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800691 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700692 outBounds.set(mBounds);
693 return;
694 }
695
696 mDisplayContent.getLogicalDisplayRect(mTmpRect);
697 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800698 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700699 getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100700 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700701
702 }
703
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700704 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700705 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700706 * @param displayRect The bounds of the display the docked stack is on.
707 * @param outBounds Output bounds that should be used for the stack.
708 * @param stackId Id of stack we are calculating the bounds for.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700709 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700710 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
711 * close to the side of the dock.
712 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700713 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800714 private void getStackDockedModeBounds(
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700715 Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
716 boolean dockOnTopOrLeft) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700717 final boolean dockedStack = stackId == DOCKED_STACK_ID;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700718 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700719
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700720 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700721 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800722 if (mService.mDockedStackCreateBounds != null) {
723 outBounds.set(mService.mDockedStackCreateBounds);
724 return;
725 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100726
727 // The initial bounds of the docked stack when it is created about half the screen space
728 // and its bounds can be adjusted after that. The bounds of all other stacks are
729 // adjusted to occupy whatever screen space the docked stack isn't occupying.
730 final DisplayInfo di = mDisplayContent.getDisplayInfo();
731 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
732 mTmpRect2);
733 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100734 di.logicalWidth,
735 di.logicalHeight,
736 dockDividerWidth,
737 mService.mCurConfiguration.orientation == ORIENTATION_PORTRAIT,
738 mTmpRect2).getMiddleTarget().position;
739
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700740 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700741 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100742 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700743 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100744 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700745 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700746 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700747 if (splitHorizontally) {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700748 outBounds.left = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700749 } else {
Andrii Kulianef3b2722016-04-08 12:45:27 -0700750 outBounds.top = position + dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700751 }
752 }
753 return;
754 }
755
756 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700757 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700758 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700759 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700760 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700761 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700762 }
763 } else {
764 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700765 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700766 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700767 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700768 }
769 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800770 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700771 }
772
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800773 void resetDockedStackToMiddle() {
774 if (mStackId != DOCKED_STACK_ID) {
775 throw new IllegalStateException("Not a docked stack=" + this);
776 }
777
778 mService.mDockedStackCreateBounds = null;
779
780 final Rect bounds = new Rect();
781 getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
782 mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
783 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
784 }
785
Craig Mautnerdc548482014-02-05 13:35:24 -0800786 void detachDisplay() {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800787 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700788
789 boolean doAnotherLayoutPass = false;
Craig Mautnerdc548482014-02-05 13:35:24 -0800790 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700791 final AppTokenList appWindowTokens = mTasks.get(taskNdx).mAppTokens;
792 for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
793 final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
794 for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
Filip Gruszczynskid66af6a2015-08-31 08:57:24 -0700795 // We are in the middle of changing the state of displays/stacks/tasks. We need
796 // to finish that, before we let layout interfere with it.
Filip Gruszczynski49b80af2015-09-24 09:04:26 -0700797 mService.removeWindowLocked(appWindows.get(winNdx));
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700798 doAnotherLayoutPass = true;
799 }
800 }
Craig Mautnerdc548482014-02-05 13:35:24 -0800801 }
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700802 if (doAnotherLayoutPass) {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700803 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700804 }
805
Craig Mautner00a66752015-03-23 14:00:47 -0700806 close();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700807 }
808
Craig Mautner05d29032013-05-03 13:40:13 -0700809 void resetAnimationBackgroundAnimator() {
810 mAnimationBackgroundAnimator = null;
811 mAnimationBackgroundSurface.hide();
812 }
813
Craig Mautner05d29032013-05-03 13:40:13 -0700814 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
815 int animLayer = winAnimator.mAnimLayer;
816 if (mAnimationBackgroundAnimator == null
817 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
818 mAnimationBackgroundAnimator = winAnimator;
819 animLayer = mService.adjustAnimationBackground(winAnimator);
820 mAnimationBackgroundSurface.show(animLayer - WindowManagerService.LAYER_OFFSET_DIM,
821 ((color >> 24) & 0xff) / 255f, 0);
822 }
823 }
824
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800825 void switchUser() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700826 int top = mTasks.size();
827 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
828 Task task = mTasks.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700829 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700830 mTasks.remove(taskNdx);
831 mTasks.add(task);
832 --top;
833 }
834 }
835 }
836
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800837 void close() {
Craig Mautner00a66752015-03-23 14:00:47 -0700838 if (mAnimationBackgroundSurface != null) {
839 mAnimationBackgroundSurface.destroySurface();
840 mAnimationBackgroundSurface = null;
841 }
Filip Gruszczynski26ed2652015-08-10 11:02:53 -0700842 mDisplayContent = null;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800843 }
844
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800845 /**
846 * Adjusts the stack bounds if the IME is visible.
847 *
848 * @param imeWin The IME window.
849 */
850 void setAdjustedForIme(WindowState imeWin) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800851 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -0700852 mImeGoingAway = false;
Jorim Jaggiff71d202016-04-14 13:12:36 -0700853 if (!mAdjustedForIme) {
854 mAdjustedForIme = true;
855 mAdjustImeAmount = 0f;
856 updateAdjustForIme(0f, true /* force */);
857 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700858 }
859
860 boolean isAdjustedForIme() {
861 return mAdjustedForIme || mImeGoingAway;
862 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700863
864 boolean isAnimatingForIme() {
865 return mImeWin != null && mImeWin.isAnimatingLw();
866 }
867
868 /**
869 * Update the stack's bounds (crop or position) according to the IME window's
870 * current position. When IME window is animated, the bottom stack is animated
871 * together to track the IME window's current position, and the top stack is
872 * cropped as necessary.
873 *
874 * @return true if a traversal should be performed after the adjustment.
875 */
Jorim Jaggiff71d202016-04-14 13:12:36 -0700876 boolean updateAdjustForIme(float adjustAmount, boolean force) {
877 if (adjustAmount != mAdjustImeAmount || force) {
Jorim Jaggieb88d832016-04-13 20:17:43 -0700878 mAdjustImeAmount = adjustAmount;
879 updateAdjustedBounds();
880 return isVisibleForUserLocked();
881 } else {
882 return false;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700883 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800884 }
885
886 /**
887 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -0700888 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
889 * animations; otherwise, set flag and animates the window away together
890 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800891 */
Chong Zhangbaba7832016-03-24 10:21:26 -0700892 void resetAdjustedForIme(boolean adjustBoundsNow) {
893 if (adjustBoundsNow) {
894 mImeWin = null;
895 mAdjustedForIme = false;
896 mImeGoingAway = false;
Jorim Jaggieb88d832016-04-13 20:17:43 -0700897 mAdjustImeAmount = 0f;
Chong Zhangbaba7832016-03-24 10:21:26 -0700898 updateAdjustedBounds();
Chong Zhang198afac2016-04-15 12:03:11 -0700899 mService.setResizeDimLayer(false, mStackId, 1.0f);
Chong Zhangbaba7832016-03-24 10:21:26 -0700900 } else {
901 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700902 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800903 }
904
905 /**
906 * Sets the amount how much we currently minimize our stack.
907 *
908 * @param minimizeAmount The amount, between 0 and 1.
909 * @return Whether the amount has changed and a layout is needed.
910 */
911 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
912 if (minimizeAmount != mMinimizeAmount) {
913 mMinimizeAmount = minimizeAmount;
914 updateAdjustedBounds();
915 return isVisibleForUserLocked();
916 } else {
917 return false;
918 }
919 }
920
Jorim Jaggi409635b2016-04-01 15:32:28 -0700921 boolean isAdjustedForMinimizedDock() {
922 return mMinimizeAmount != 0f;
923 }
924
Jorim Jaggiff71d202016-04-14 13:12:36 -0700925 /**
926 * Puts all visible tasks that are adjusted for IME into resizing mode and adds the windows
927 * to the list of to be drawn windows the service is waiting for.
928 */
929 void beginImeAdjustAnimation() {
930 for (int j = mTasks.size() - 1; j >= 0; j--) {
931 final Task task = mTasks.get(j);
932 if (task.isVisibleForUser()) {
933 task.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
934 task.addWindowsWaitingForDrawnIfResizingChanged();
935 }
936 }
937 }
938
939 /**
940 * Resets the resizing state of all windows.
941 */
942 void endImeAdjustAnimation() {
943 for (int j = mTasks.size() - 1; j >= 0; j--) {
944 mTasks.get(j).setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
945 }
946 }
947
Chong Zhang198afac2016-04-15 12:03:11 -0700948 int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
949 return displayContentRect.top + (int)
950 ((originalStackBottom - displayContentRect.top) * ADJUSTED_STACK_FRACTION_MIN);
951 }
952
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800953 private boolean adjustForIME(final WindowState imeWin) {
954 final int dockedSide = getDockSide();
955 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800956 if (imeWin == null || !dockedTopOrBottom) {
957 return false;
958 }
959
960 final Rect displayContentRect = mTmpRect;
961 final Rect contentBounds = mTmpRect2;
962
963 // Calculate the content bounds excluding the area occupied by IME
964 getDisplayContent().getContentRect(displayContentRect);
965 contentBounds.set(displayContentRect);
Jorim Jaggi5ac2ba22016-04-11 21:14:12 -0700966 int imeTop = Math.max(imeWin.getFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -0700967
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800968 imeTop += imeWin.getGivenContentInsetsLw().top;
969 if (contentBounds.bottom > imeTop) {
970 contentBounds.bottom = imeTop;
971 }
972
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800973 mLastContentBounds.set(contentBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800974 final int yOffset = displayContentRect.bottom - contentBounds.bottom;
975
Chong Zhang198afac2016-04-15 12:03:11 -0700976 final int dividerWidth =
977 getDisplayContent().mDividerControllerLocked.getContentWidth();
978 final int dividerWidthInactive =
979 getDisplayContent().mDividerControllerLocked.getContentWidthInactive();
980
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800981 if (dockedSide == DOCKED_TOP) {
982 // If this stack is docked on top, we make it smaller so the bottom stack is not
Chong Zhang198afac2016-04-15 12:03:11 -0700983 // occluded by IME. We shift its bottom up by the height of the IME, but
984 // leaves at least 30% of the top stack visible.
985 final int minTopStackBottom =
986 getMinTopStackBottom(displayContentRect, mBounds.bottom);
987 final int bottom = Math.max(
988 mBounds.bottom - yOffset + dividerWidth - dividerWidthInactive,
989 minTopStackBottom);
Jorim Jaggieb88d832016-04-13 20:17:43 -0700990 mTmpAdjustedBounds.set(mBounds);
991 mTmpAdjustedBounds.bottom =
992 (int) (mAdjustImeAmount * bottom + (1 - mAdjustImeAmount) * mBounds.bottom);
993 mFullyAdjustedImeBounds.set(mBounds);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800994 } else {
Chong Zhang198afac2016-04-15 12:03:11 -0700995 final int top;
996 final boolean isFocusedStack = mService.getFocusedStackLocked() == this;
997 if (isFocusedStack) {
998 // If this stack is docked on bottom and has focus, we shift it up so that it's not
999 // occluded by IME. We try to move it up by the height of the IME window, but only
1000 // to the extent that leaves at least 30% of the top stack visible.
1001 final int minTopStackBottom =
1002 getMinTopStackBottom(displayContentRect, mBounds.top - dividerWidth);
1003 top = Math.max(
1004 mBounds.top - yOffset, minTopStackBottom + dividerWidthInactive);
1005 } else {
1006 // If this stack is docked on bottom but doesn't have focus, we don't need to adjust
1007 // for IME, but still need to apply a small adjustment due to the thinner divider.
1008 top = mBounds.top - dividerWidth + dividerWidthInactive;
1009 }
1010
Jorim Jaggieb88d832016-04-13 20:17:43 -07001011 mTmpAdjustedBounds.set(mBounds);
1012 mTmpAdjustedBounds.top =
1013 (int) (mAdjustImeAmount * top + (1 - mAdjustImeAmount) * mBounds.top);
Jorim Jaggieb88d832016-04-13 20:17:43 -07001014 mFullyAdjustedImeBounds.set(mBounds);
1015 mFullyAdjustedImeBounds.top = top;
1016 mFullyAdjustedImeBounds.bottom = top + mBounds.height();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001017 }
1018 return true;
1019 }
1020
1021 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
1022 final int dockSide = getDockSide();
1023 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
1024 return false;
1025 }
1026
1027 if (dockSide == DOCKED_TOP) {
1028 mService.getStableInsetsLocked(mTmpRect);
1029 int topInset = mTmpRect.top;
1030 mTmpAdjustedBounds.set(mBounds);
1031 mTmpAdjustedBounds.bottom =
1032 (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
1033 } else if (dockSide == DOCKED_LEFT) {
1034 mTmpAdjustedBounds.set(mBounds);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001035 final int width = mBounds.width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001036 mTmpAdjustedBounds.right =
1037 (int) (minimizeAmount * mDockedStackMinimizeThickness
1038 + (1 - minimizeAmount) * mBounds.right);
Jorim Jaggibcff1432016-04-01 15:49:45 -07001039 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001040 } else if (dockSide == DOCKED_RIGHT) {
1041 mTmpAdjustedBounds.set(mBounds);
1042 mTmpAdjustedBounds.left =
1043 (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
1044 + (1 - minimizeAmount) * mBounds.left);
1045 }
1046 return true;
1047 }
1048
1049 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -08001050 * @return the distance in pixels how much the stack gets minimized from it's original size
1051 */
1052 int getMinimizeDistance() {
1053 final int dockSide = getDockSide();
1054 if (dockSide == DOCKED_INVALID) {
1055 return 0;
1056 }
1057
1058 if (dockSide == DOCKED_TOP) {
1059 mService.getStableInsetsLocked(mTmpRect);
1060 int topInset = mTmpRect.top;
1061 return mBounds.bottom - topInset;
1062 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
1063 return mBounds.width() - mDockedStackMinimizeThickness;
1064 } else {
1065 return 0;
1066 }
1067 }
1068
1069 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001070 * Updates the adjustment depending on it's current state.
1071 */
Jorim Jaggieb88d832016-04-13 20:17:43 -07001072 void updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001073 boolean adjust = false;
1074 if (mMinimizeAmount != 0f) {
1075 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1076 } else if (mAdjustedForIme) {
1077 adjust = adjustForIME(mImeWin);
1078 }
1079 if (!adjust) {
1080 mTmpAdjustedBounds.setEmpty();
1081 mLastContentBounds.setEmpty();
1082 }
Jorim Jaggieb88d832016-04-13 20:17:43 -07001083 setAdjustedBounds(mTmpAdjustedBounds);
Chong Zhang198afac2016-04-15 12:03:11 -07001084
1085 final boolean isFocusedStack = mService.getFocusedStackLocked() == this;
1086 if (mAdjustedForIme && adjust && !isFocusedStack) {
1087 final float alpha = mAdjustImeAmount * IME_ADJUST_DIM_AMOUNT;
1088 mService.setResizeDimLayer(true, mStackId, alpha);
1089 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001090 }
1091
1092 boolean isAdjustedForMinimizedDockedStack() {
1093 return mMinimizeAmount != 0f;
1094 }
1095
Craig Mautner00af9fe2013-03-25 09:13:41 -07001096 public void dump(String prefix, PrintWriter pw) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001097 pw.println(prefix + "mStackId=" + mStackId);
1098 pw.println(prefix + "mDeferDetach=" + mDeferDetach);
1099 pw.println(prefix + "mFullscreen=" + mFullscreen);
1100 pw.println(prefix + "mBounds=" + mBounds.toShortString());
Jorim Jaggieb88d832016-04-13 20:17:43 -07001101 if (!mAdjustedBounds.isEmpty()) {
1102 pw.println(prefix + "mAdjustedBounds=" + mAdjustedBounds.toShortString());
1103 }
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001104 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; taskNdx--) {
1105 mTasks.get(taskNdx).dump(prefix + " ", pw);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001106 }
Craig Mautner05d29032013-05-03 13:40:13 -07001107 if (mAnimationBackgroundSurface.isDimming()) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001108 pw.println(prefix + "mWindowAnimationBackgroundSurface:");
Craig Mautner05d29032013-05-03 13:40:13 -07001109 mAnimationBackgroundSurface.printTo(prefix + " ", pw);
1110 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001111 if (!mExitingAppTokens.isEmpty()) {
1112 pw.println();
1113 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001114 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001115 WindowToken token = mExitingAppTokens.get(i);
1116 pw.print(" Exiting App #"); pw.print(i);
1117 pw.print(' '); pw.print(token);
1118 pw.println(':');
1119 token.dump(pw, " ");
1120 }
1121 }
Craig Mautner00af9fe2013-03-25 09:13:41 -07001122 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001123
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001124 /** Fullscreen status of the stack without adjusting for other factors in the system like
1125 * visibility of docked stack.
1126 * Most callers should be using {@link #isFullscreen} as it take into consideration other
1127 * system factors. */
1128 boolean getRawFullscreen() {
1129 return mFullscreen;
1130 }
1131
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001132 @Override
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001133 public boolean isFullscreen() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001134 if (useCurrentBounds()) {
1135 return mFullscreen;
1136 }
1137 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
1138 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
1139 // system.
1140 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001141 }
1142
1143 @Override
1144 public DisplayInfo getDisplayInfo() {
1145 return mDisplayContent.getDisplayInfo();
1146 }
1147
1148 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001149 public String toString() {
1150 return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
1151 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001152
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001153 @Override
1154 public String toShortString() {
1155 return "Stack=" + mStackId;
1156 }
1157
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001158 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001159 * For docked workspace (or workspace that's side-by-side to the docked), provides
1160 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001161 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001162 int getDockSide() {
Jorim Jaggi737af722015-12-31 10:42:27 +01001163 return getDockSide(mBounds);
1164 }
1165
1166 int getDockSide(Rect bounds) {
Chong Zhangc806d902015-11-30 09:44:27 -08001167 if (mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId)) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001168 return DOCKED_INVALID;
1169 }
1170 if (mDisplayContent == null) {
1171 return DOCKED_INVALID;
1172 }
1173 mDisplayContent.getLogicalDisplayRect(mTmpRect);
1174 final int orientation = mService.mCurConfiguration.orientation;
1175 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
1176 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi067e8172016-02-03 18:24:12 -08001177 if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001178 return DOCKED_TOP;
1179 } else {
1180 return DOCKED_BOTTOM;
1181 }
1182 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1183 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi067e8172016-02-03 18:24:12 -08001184 if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001185 return DOCKED_LEFT;
1186 } else {
1187 return DOCKED_RIGHT;
1188 }
1189 } else {
1190 return DOCKED_INVALID;
1191 }
1192 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001193
1194 boolean isVisibleLocked() {
Jorim Jaggi7998e482016-02-12 18:47:06 -08001195 final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded()
1196 && !mService.mAnimator.mKeyguardGoingAway;
Chong Zhang75b37202015-12-04 14:16:36 -08001197 if (keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -08001198 // The keyguard is showing and the stack shouldn't show on top of the keyguard.
Wale Ogunwale961f4852016-02-01 20:25:54 -08001199 return false;
Chong Zhang75b37202015-12-04 14:16:36 -08001200 }
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -08001201
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001202 for (int i = mTasks.size() - 1; i >= 0; i--) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001203 final Task task = mTasks.get(i);
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001204 for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
1205 if (!task.mAppTokens.get(j).hidden) {
1206 return true;
1207 }
1208 }
1209 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001210
1211 return false;
1212 }
1213
1214 /**
1215 * @return true if a the stack is visible for the current in user, ignoring any other visibility
1216 * aspects, and false otherwise
1217 */
1218 boolean isVisibleForUserLocked() {
1219 for (int i = mTasks.size() - 1; i >= 0; i--) {
1220 final Task task = mTasks.get(i);
1221 if (task.isVisibleForUser()) {
1222 return true;
1223 }
1224 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001225 return false;
1226 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001227
Wale Ogunwalece144522016-02-05 22:51:01 -08001228 boolean isDragResizing() {
1229 return mDragResizing;
1230 }
1231
Jorim Jaggiff71d202016-04-14 13:12:36 -07001232 void setDragResizingLocked(boolean resizing) {
Jorim Jaggic662d8e2016-02-05 16:54:54 -08001233 if (mDragResizing == resizing) {
1234 return;
1235 }
1236 mDragResizing = resizing;
1237 for (int i = mTasks.size() - 1; i >= 0 ; i--) {
1238 mTasks.get(i).resetDragResizingChangeReported();
1239 }
1240 }
1241
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001242 @Override // AnimatesBounds
1243 public boolean setSize(Rect bounds) {
1244 synchronized (mService.mWindowMap) {
1245 if (mDisplayContent == null) {
1246 return false;
1247 }
1248 }
1249 try {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001250 mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false, -1);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001251 } catch (RemoteException e) {
1252 }
1253 return true;
1254 }
1255
Robert Carr0d00c2e2016-02-29 17:45:02 -08001256 public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
1257 synchronized (mService.mWindowMap) {
1258 if (mDisplayContent == null) {
1259 return false;
1260 }
1261 if (mStackId != PINNED_STACK_ID) {
1262 Slog.w(TAG_WM, "Attempt to use pinned stack resize animation helper on"
1263 + "non pinned stack");
1264 return false;
1265 }
1266 }
1267 try {
1268 mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
1269 } catch (RemoteException e) {
1270 // I don't believe you.
1271 }
1272 return true;
1273 }
1274
Robert Carr1ca6a332016-04-11 18:00:43 -07001275 void forceWindowsScaleable(boolean force) {
1276 SurfaceControl.openTransaction();
1277 try {
1278 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
1279 final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
1280 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1281 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
1282 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
1283 final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
1284 if (winAnimator == null || !winAnimator.hasSurface()) {
1285 continue;
1286 }
1287 winAnimator.mSurfaceController.forceScaleableInTransaction(force);
1288 }
1289 }
1290 }
1291 } finally {
1292 SurfaceControl.closeTransaction();
1293 }
1294 }
1295
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001296 @Override // AnimatesBounds
Wale Ogunwalece144522016-02-05 22:51:01 -08001297 public void onAnimationStart() {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001298 synchronized (mService.mWindowMap) {
Robert Carr1ca6a332016-04-11 18:00:43 -07001299 // We force windows out of SCALING_MODE_FREEZE
1300 // so that we can continue to animate them
1301 // while a resize is pending.
1302 forceWindowsScaleable(true);
Robert Carr0d00c2e2016-02-29 17:45:02 -08001303 mFreezeMovementAnimations = true;
Robert Carr1ca6a332016-04-11 18:00:43 -07001304 mBoundsAnimating = true;
Wale Ogunwalece144522016-02-05 22:51:01 -08001305 }
1306 }
1307
1308 @Override // AnimatesBounds
1309 public void onAnimationEnd() {
1310 synchronized (mService.mWindowMap) {
Robert Carr0d00c2e2016-02-29 17:45:02 -08001311 mFreezeMovementAnimations = false;
Robert Carr1ca6a332016-04-11 18:00:43 -07001312 mBoundsAnimating = false;
1313 forceWindowsScaleable(false);
Wale Ogunwalece144522016-02-05 22:51:01 -08001314 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001315 }
Wale Ogunwale480dca02016-02-06 13:58:29 -08001316 if (mStackId == PINNED_STACK_ID) {
1317 try {
1318 mService.mActivityManager.notifyPinnedStackAnimationEnded();
1319 } catch (RemoteException e) {
1320 // I don't believe you...
1321 }
1322 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001323 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001324
1325 @Override
1326 public void moveToFullscreen() {
1327 try {
1328 mService.mActivityManager.moveTasksToFullscreenStack(mStackId, true);
1329 } catch (RemoteException e) {
1330 e.printStackTrace();
1331 }
1332 }
1333
1334 @Override
1335 public void getFullScreenBounds(Rect bounds) {
1336 getDisplayContent().getContentRect(bounds);
1337 }
Robert Carr0d00c2e2016-02-29 17:45:02 -08001338
1339 public boolean getFreezeMovementAnimations() {
1340 return mFreezeMovementAnimations;
1341 }
1342
1343 public boolean getForceScaleToCrop() {
Robert Carr1ca6a332016-04-11 18:00:43 -07001344 return mBoundsAnimating;
1345 }
1346
1347 public boolean getBoundsAnimating() {
1348 return mBoundsAnimating;
Robert Carr0d00c2e2016-02-29 17:45:02 -08001349 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001350}