blob: a8b728923265203ed1d74ce47cae92996dcf3aed [file] [log] [blame]
Craig Mautnerc00204b2013-03-05 15:02:14 -08001/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Wale Ogunwale3797c222015-10-27 14:21:58 -070019import android.app.ActivityManager.StackId;
Wale Ogunwale60454db2015-01-23 16:05:07 -080020import android.content.res.Configuration;
Craig Mautner05d29032013-05-03 13:40:13 -070021import android.graphics.Rect;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070022import android.os.Debug;
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080023import android.os.RemoteException;
Craig Mautner2c2549c2013-11-12 08:31:15 -080024import android.util.EventLog;
Craig Mautnerf0ac5c82013-06-24 11:21:57 -070025import android.util.Slog;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070026import android.util.SparseArray;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070027import android.view.DisplayInfo;
Wale Ogunwale94744212015-09-21 19:01:47 -070028import android.view.Surface;
Filip Gruszczynski54977fe2015-10-19 17:26:45 -070029
Jorim Jaggi737af722015-12-31 10:42:27 +010030import com.android.internal.policy.DividerSnapAlgorithm;
31import com.android.internal.policy.DividerSnapAlgorithm.SnapTarget;
32import com.android.internal.policy.DockedDividerUtils;
Craig Mautner2c2549c2013-11-12 08:31:15 -080033import com.android.server.EventLogTags;
Craig Mautner05d29032013-05-03 13:40:13 -070034
Craig Mautner00af9fe2013-03-25 09:13:41 -070035import java.io.PrintWriter;
Craig Mautnerc00204b2013-03-05 15:02:14 -080036import java.util.ArrayList;
37
Jorim Jaggi61f39a72015-10-29 16:54:18 +010038import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
39import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
40import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
Jorim Jaggid434dcb2016-01-06 17:18:44 +010041import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010042import static android.view.WindowManager.DOCKED_BOTTOM;
43import static android.view.WindowManager.DOCKED_INVALID;
44import static android.view.WindowManager.DOCKED_LEFT;
45import static android.view.WindowManager.DOCKED_RIGHT;
46import static android.view.WindowManager.DOCKED_TOP;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080047import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010048import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080049import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010050
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080051public class TaskStack implements DimLayer.DimLayerUser,
52 BoundsAnimationController.AnimateBoundsUser {
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070053
54 // If the stack should be resized to fullscreen.
55 private static final boolean FULLSCREEN = true;
56
Craig Mautner00af9fe2013-03-25 09:13:41 -070057 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080058 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070059
Craig Mautner05d29032013-05-03 13:40:13 -070060 /** The service */
61 private final WindowManagerService mService;
62
Craig Mautner00af9fe2013-03-25 09:13:41 -070063 /** The display this stack sits under. */
Craig Mautnerdf88d732014-01-27 09:21:32 -080064 private DisplayContent mDisplayContent;
Craig Mautner00af9fe2013-03-25 09:13:41 -070065
66 /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match
67 * mTaskHistory in the ActivityStack with the same mStackId */
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070068 private final ArrayList<Task> mTasks = new ArrayList<>();
Craig Mautner00af9fe2013-03-25 09:13:41 -070069
Craig Mautnerb660b9d2014-02-13 10:59:16 -080070 /** For comparison with DisplayContent bounds. */
71 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070072 private Rect mTmpRect2 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -080073
74 /** Content limits relative to the DisplayContent this sits in. */
75 private Rect mBounds = new Rect();
76
Chong Zhangb816b862016-01-25 12:01:12 -080077 /** Screen content area excluding IM windows, etc. */
78 private final Rect mContentBounds = new Rect();
79
80 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
81 private final Rect mAdjustedBounds = new Rect();
82
Craig Mautnerb660b9d2014-02-13 10:59:16 -080083 /** Whether mBounds is fullscreen */
84 private boolean mFullscreen = true;
Craig Mautnerc00204b2013-03-05 15:02:14 -080085
Wale Ogunwale94744212015-09-21 19:01:47 -070086 // Device rotation as of the last time {@link #mBounds} was set.
87 int mRotation;
88
Craig Mautner05d29032013-05-03 13:40:13 -070089 /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
Craig Mautnerdf88d732014-01-27 09:21:32 -080090 DimLayer mAnimationBackgroundSurface;
Craig Mautner05d29032013-05-03 13:40:13 -070091
92 /** The particular window with an Animation with non-zero background color. */
93 WindowStateAnimator mAnimationBackgroundAnimator;
94
Craig Mautnerdc548482014-02-05 13:35:24 -080095 /** Application tokens that are exiting, but still on screen for animations. */
96 final AppTokenList mExitingAppTokens = new AppTokenList();
97
Craig Mautner95da1082014-02-24 17:54:35 -080098 /** Detach this stack from its display when animation completes. */
99 boolean mDeferDetach;
Filip Gruszczynskidce2d162016-01-12 15:40:13 -0800100 private boolean mUpdateBoundsAfterRotation = false;
Craig Mautner95da1082014-02-24 17:54:35 -0800101
Wale Ogunwalece144522016-02-05 22:51:01 -0800102 // Whether the stack and all its tasks is currently being drag-resized
103 private boolean mDragResizing;
104
Craig Mautnerdf88d732014-01-27 09:21:32 -0800105 TaskStack(WindowManagerService service, int stackId) {
Craig Mautner05d29032013-05-03 13:40:13 -0700106 mService = service;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800107 mStackId = stackId;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700108 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800109 }
110
111 DisplayContent getDisplayContent() {
112 return mDisplayContent;
113 }
114
Craig Mautnerd9a22882013-03-16 15:00:36 -0700115 ArrayList<Task> getTasks() {
116 return mTasks;
117 }
118
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700119 /**
120 * Set the bounds of the stack and its containing tasks.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700121 * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700122 * @param configs Configuration for individual tasks, keyed by task id.
123 * @param taskBounds Bounds for individual tasks, keyed by task id.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700124 * @return True if the stack bounds was changed.
125 * */
Wale Ogunwalea6e902e2015-09-21 18:37:15 -0700126 boolean setBounds(
Jorim Jaggidc249c42015-12-15 14:57:31 -0800127 Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
128 SparseArray<Rect> taskTempInsetBounds) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700129 if (!setBounds(stackBounds)) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700130 return false;
131 }
132
133 // Update bounds of containing tasks.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700134 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
135 final Task task = mTasks.get(taskNdx);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700136 Configuration config = configs.get(task.mTaskId);
137 if (config != null) {
138 Rect bounds = taskBounds.get(task.mTaskId);
Chong Zhang2a88fc32016-01-11 17:14:24 -0800139 if (task.isTwoFingerScrollMode()) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800140 // This is a non-resizeable task that's docked (or side-by-side to the docked
141 // stack). It might have been scrolled previously, and after the stack resizing,
142 // it might no longer fully cover the stack area.
143 // Save the old bounds and re-apply the scroll. This adjusts the bounds to
144 // fit the new stack bounds.
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100145 task.resizeLocked(bounds, config, false /* forced */);
Chong Zhangf66db432016-01-13 10:39:51 -0800146 task.getBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800147 task.scrollLocked(mTmpRect);
148 } else {
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100149 task.resizeLocked(bounds, config, false /* forced */);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800150 task.setTempInsetBounds(
151 taskTempInsetBounds != null ? taskTempInsetBounds.get(task.mTaskId)
152 : null);
Chong Zhangb15758a2015-11-17 12:12:03 -0800153 }
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700154 } else {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800155 Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700156 }
157 }
158 return true;
159 }
160
Jorim Jaggi0429f352015-12-22 16:29:16 +0100161 void prepareFreezingTaskBounds() {
162 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
163 final Task task = mTasks.get(taskNdx);
164 task.prepareFreezingBounds();
165 }
166 }
167
Wale Ogunwaleb4ec0a32015-12-14 10:31:43 -0800168 boolean isFullscreenBounds(Rect bounds) {
169 if (mDisplayContent == null || bounds == null) {
170 return true;
171 }
172 mDisplayContent.getLogicalDisplayRect(mTmpRect);
173 return mTmpRect.equals(bounds);
174 }
175
Chong Zhangb816b862016-01-25 12:01:12 -0800176 void alignTasksToAdjustedBounds(final Rect adjustedBounds) {
177 if (mFullscreen) {
178 return;
179 }
180 // Update bounds of containing tasks.
181 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
182 final Task task = mTasks.get(taskNdx);
183 if (task.isTwoFingerScrollMode()) {
184 // If we're scrolling we don't care about your bounds or configs,
185 // they should be null as if we were in fullscreen.
186 task.resizeLocked(null, null, false /* forced */);
187 task.getBounds(mTmpRect2);
188 task.scrollLocked(mTmpRect2);
189 } else if (task.isResizeable()) {
190 task.getBounds(mTmpRect2);
191 mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
192 task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */);
193 }
194 }
195 }
196
197 void adjustForIME(final WindowState imeWin) {
198 final int dockedSide = getDockSide();
199 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
200 final Rect adjustedBounds = mAdjustedBounds;
201 if (imeWin == null || !dockedTopOrBottom) {
202 // If mContentBounds is already empty, it means we're not applying
203 // any adjustments, so nothing to do; otherwise clear any adjustments.
204 if (!mContentBounds.isEmpty()) {
205 mContentBounds.setEmpty();
206 adjustedBounds.set(mBounds);
207 alignTasksToAdjustedBounds(adjustedBounds);
208 }
209 return;
210 }
211
212 final Rect displayContentRect = mTmpRect;
213 final Rect contentBounds = mTmpRect2;
214
215 // Calculate the content bounds excluding the area occupied by IME
216 mDisplayContent.getContentRect(displayContentRect);
217 contentBounds.set(displayContentRect);
218 int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top);
219 imeTop += imeWin.getGivenContentInsetsLw().top;
220 if (contentBounds.bottom > imeTop) {
221 contentBounds.bottom = imeTop;
222 }
223
224 // If content bounds not changing, nothing to do.
225 if (mContentBounds.equals(contentBounds)) {
226 return;
227 }
228
229 // Content bounds changed, need to apply adjustments depending on dock sides.
230 mContentBounds.set(contentBounds);
231 adjustedBounds.set(mBounds);
232 final int yOffset = displayContentRect.bottom - contentBounds.bottom;
233
234 if (dockedSide == DOCKED_TOP) {
235 // If this stack is docked on top, we make it smaller so the bottom stack is not
236 // occluded by IME. We shift its bottom up by the height of the IME (capped by
237 // the display content rect). Note that we don't change the task bounds.
238 adjustedBounds.bottom = Math.max(
239 adjustedBounds.bottom - yOffset, displayContentRect.top);
240 } else {
241 // If this stack is docked on bottom, we shift it up so that it's not occluded by
242 // IME. We try to move it up by the height of the IME window (although the best
243 // we could do is to make the top stack fully collapsed).
244 final int dividerWidth = mDisplayContent.mDividerControllerLocked.getContentWidth();
245 adjustedBounds.top = Math.max(
246 adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth);
247 adjustedBounds.bottom = adjustedBounds.top + mBounds.height();
248
249 // We also move the member tasks together, taking care not to resize them.
250 // Resizing might cause relaunch, and IME window may not come back after that.
251 alignTasksToAdjustedBounds(adjustedBounds);
252 }
253 }
254
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700255 private boolean setBounds(Rect bounds) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800256 boolean oldFullscreen = mFullscreen;
Wale Ogunwale94744212015-09-21 19:01:47 -0700257 int rotation = Surface.ROTATION_0;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800258 if (mDisplayContent != null) {
259 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwale94744212015-09-21 19:01:47 -0700260 rotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi067e8172016-02-03 18:24:12 -0800261 mFullscreen = bounds == null;
262 if (mFullscreen) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800263 bounds = mTmpRect;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800264 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800265 }
266
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800267 if (bounds == null) {
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800268 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800269 return false;
270 }
Wale Ogunwale94744212015-09-21 19:01:47 -0700271 if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800272 return false;
273 }
274
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700275 if (mDisplayContent != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800276 mDisplayContent.mDimLayerController.updateDimLayer(this);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700277 mAnimationBackgroundSurface.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700278 }
279
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800280 mBounds.set(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700281 mRotation = rotation;
Chong Zhangb816b862016-01-25 12:01:12 -0800282
283 // Clear the adjusted content bounds as they're no longer valid.
284 // If IME is still visible, these will be re-applied.
285 // Note that we don't clear mContentBounds here, so that we know the last IME
286 // adjust we applied.
287 // If user starts dragging the dock divider while IME is visible, the new bounds
288 // we received are based on the actual screen location of the divider. It already
289 // accounted for the IME window, so we don't want to adjust again.
290 mAdjustedBounds.set(mBounds);
291
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800292 return true;
293 }
294
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700295 /** Bounds of the stack without adjusting for other factors in the system like visibility
296 * of docked stack.
297 * Most callers should be using {@link #getBounds} as it take into consideration other system
298 * factors. */
299 void getRawBounds(Rect out) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800300 out.set(mBounds);
301 }
302
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700303 /** Return true if the current bound can get outputted to the rest of the system as-is. */
304 private boolean useCurrentBounds() {
305 if (mFullscreen
Wale Ogunwale3797c222015-10-27 14:21:58 -0700306 || !StackId.isResizeableByDockedStack(mStackId)
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700307 || mDisplayContent == null
308 || mDisplayContent.getDockedStackLocked() != null) {
309 return true;
310 }
311 return false;
312 }
313
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700314 public void getBounds(Rect out) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700315 if (useCurrentBounds()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800316 // If we're currently adjusting for IME, we use the adjusted bounds; otherwise,
317 // no need to adjust the output bounds if fullscreen or the docked stack is visible
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700318 // since it is already what we want to represent to the rest of the system.
Chong Zhangb816b862016-01-25 12:01:12 -0800319 if (!mContentBounds.isEmpty()) {
320 out.set(mAdjustedBounds);
321 } else {
322 out.set(mBounds);
323 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700324 return;
325 }
326
327 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
328 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
329 // system.
330 mDisplayContent.getLogicalDisplayRect(out);
331 }
332
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800333 /** Bounds of the stack with other system factors taken into consideration. */
334 @Override
335 public void getDimBounds(Rect out) {
336 getBounds(out);
337 }
338
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700339 void updateDisplayInfo(Rect bounds) {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -0800340 mUpdateBoundsAfterRotation = false;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700341 if (mDisplayContent != null) {
Wale Ogunwale1ed0d892015-09-28 13:27:44 -0700342 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
343 mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
344 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700345 if (bounds != null) {
346 setBounds(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700347 } else if (mFullscreen) {
348 setBounds(null);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700349 } else {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -0800350 mUpdateBoundsAfterRotation = true;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700351 mTmpRect2.set(mBounds);
Jorim Jaggi737af722015-12-31 10:42:27 +0100352 final int newRotation = mDisplayContent.getDisplayInfo().rotation;
353 if (mRotation == newRotation) {
354 setBounds(mTmpRect2);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -0700355 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100356
357 // If the rotation changes, we'll handle it in updateBoundsAfterRotation
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800358 }
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800359 }
360 }
361
Jorim Jaggi737af722015-12-31 10:42:27 +0100362 /**
363 * Updates the bounds after rotating the screen. We can't handle it in
364 * {@link #updateDisplayInfo} because at that point the configuration might not be fully updated
365 * yet.
366 */
367 void updateBoundsAfterRotation() {
Filip Gruszczynskidce2d162016-01-12 15:40:13 -0800368 if (!mUpdateBoundsAfterRotation) {
369 return;
370 }
371 mUpdateBoundsAfterRotation = false;
Jorim Jaggi737af722015-12-31 10:42:27 +0100372 final int newRotation = getDisplayInfo().rotation;
373 mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
374 if (mStackId == DOCKED_STACK_ID) {
375 snapDockedStackAfterRotation(mTmpRect2);
376 }
377
378 // Post message to inform activity manager of the bounds change simulating
379 // a one-way call. We do this to prevent a deadlock between window manager
380 // lock and activity manager lock been held.
381 mService.mH.sendMessage(mService.mH.obtainMessage(
382 RESIZE_STACK, mStackId, 0 /*allowResizeInDockedMode*/, mTmpRect2));
383 }
384
385 /**
386 * Snaps the bounds after rotation to the closest snap target for the docked stack.
387 */
388 private void snapDockedStackAfterRotation(Rect outBounds) {
389
390 // Calculate the current position.
391 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
392 final int dividerSize = mService.getDefaultDisplayContentLocked()
393 .getDockedDividerController().getContentWidth();
394 final int dockSide = getDockSide(outBounds);
395 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
396 dockSide, dividerSize);
397 final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
398 final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
399
400 // Snap the position to a target.
401 final int rotation = displayInfo.rotation;
402 final int orientation = mService.mCurConfiguration.orientation;
403 mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
404 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Jorim Jaggidf012d52016-01-15 22:40:13 -0800405 mService.mContext.getResources(), displayWidth, displayHeight,
Jorim Jaggi737af722015-12-31 10:42:27 +0100406 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds);
407 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
408
409 // Recalculate the bounds based on the position of the target.
410 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
411 outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
412 dividerSize);
413 }
414
Craig Mautner1bf2b872014-02-05 15:37:40 -0800415 boolean isAnimating() {
416 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
417 final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
418 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
419 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
420 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700421 final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
Craig Mautner7c9ee192014-08-14 16:08:26 -0700422 if (winAnimator.isAnimating() || winAnimator.mWin.mExiting) {
Craig Mautner1bf2b872014-02-05 15:37:40 -0800423 return true;
424 }
425 }
426 }
427 }
428 return false;
429 }
430
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700431 void addTask(Task task, boolean toTop) {
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700432 addTask(task, toTop, task.showForAllUsers());
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700433 }
434
Craig Mautner00af9fe2013-03-25 09:13:41 -0700435 /**
436 * Put a Task in this stack. Used for adding and moving.
437 * @param task The task to add.
438 * @param toTop Whether to add it to the top or bottom.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700439 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700440 */
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700441 void addTask(Task task, boolean toTop, boolean showForAllUsers) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700442 positionTask(task, toTop ? mTasks.size() : 0, showForAllUsers);
443 }
444
445 void positionTask(Task task, int position, boolean showForAllUsers) {
446 final boolean canShowTask =
447 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
448 mTasks.remove(task);
449 int stackSize = mTasks.size();
450 int minPosition = 0;
451 int maxPosition = stackSize;
452
453 if (canShowTask) {
454 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700455 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700456 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700457 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700458 // Reset position based on minimum/maximum possible positions.
459 position = Math.min(Math.max(position, minPosition), maxPosition);
460
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800461 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM,
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700462 "positionTask: task=" + task + " position=" + position);
463 mTasks.add(position, task);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700464
Chong Zhangf66db432016-01-13 10:39:51 -0800465 // If we are moving the task across stacks, the scroll is no longer valid.
466 if (task.mStack != this) {
467 task.resetScrollLocked();
468 }
Craig Mautner967212c2013-04-13 21:10:58 -0700469 task.mStack = this;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700470 task.updateDisplayInfo(mDisplayContent);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700471 boolean toTop = position == mTasks.size() - 1;
raysb.kim00a27252014-11-11 08:38:21 +0900472 if (toTop) {
473 mDisplayContent.moveStack(this, true);
474 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700475 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, position);
476 }
477
478 /** Calculate the minimum possible position for a task that can be shown to the user.
479 * The minimum position will be above all other tasks that can't be shown.
480 * @param minPosition The minimum position the caller is suggesting.
481 * We will start adjusting up from here.
482 * @param size The size of the current task list.
483 */
484 private int computeMinPosition(int minPosition, int size) {
485 while (minPosition < size) {
486 final Task tmpTask = mTasks.get(minPosition);
487 final boolean canShowTmpTask =
488 tmpTask.showForAllUsers()
489 || mService.isCurrentProfileLocked(tmpTask.mUserId);
490 if (canShowTmpTask) {
491 break;
492 }
493 minPosition++;
494 }
495 return minPosition;
496 }
497
498 /** Calculate the maximum possible position for a task that can't be shown to the user.
499 * The maximum position will be below all other tasks that can be shown.
500 * @param maxPosition The maximum position the caller is suggesting.
501 * We will start adjusting down from here.
502 */
503 private int computeMaxPosition(int maxPosition) {
504 while (maxPosition > 0) {
505 final Task tmpTask = mTasks.get(maxPosition - 1);
506 final boolean canShowTmpTask =
507 tmpTask.showForAllUsers()
508 || mService.isCurrentProfileLocked(tmpTask.mUserId);
509 if (!canShowTmpTask) {
510 break;
511 }
512 maxPosition--;
513 }
514 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800515 }
516
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800517 void moveTaskToTop(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800518 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToTop: task=" + task + " Callers="
Craig Mautnerf0ac5c82013-06-24 11:21:57 -0700519 + Debug.getCallers(6));
Craig Mautnerd9a22882013-03-16 15:00:36 -0700520 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800521 addTask(task, true);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700522 }
523
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800524 void moveTaskToBottom(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800525 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToBottom: task=" + task);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700526 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800527 addTask(task, false);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700528 }
529
Craig Mautner00af9fe2013-03-25 09:13:41 -0700530 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800531 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
532 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700533 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700534 */
Craig Mautnerde4ef022013-04-07 19:01:33 -0700535 void removeTask(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800536 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeTask: task=" + task);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700537 mTasks.remove(task);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800538 if (mDisplayContent != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800539 if (mTasks.isEmpty()) {
540 mDisplayContent.moveStack(this, false);
541 }
542 mDisplayContent.layoutNeeded = true;
Craig Mautner04a0ea62014-01-13 12:51:26 -0800543 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800544 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
545 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Craig Mautner83162a92015-01-26 14:43:30 -0800546 if (wtoken.mTask == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800547 wtoken.mIsExiting = false;
548 mExitingAppTokens.remove(appNdx);
549 }
550 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800551 }
552
Craig Mautnerdf88d732014-01-27 09:21:32 -0800553 void attachDisplayContent(DisplayContent displayContent) {
554 if (mDisplayContent != null) {
555 throw new IllegalStateException("attachDisplayContent: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800556 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800557
558 mDisplayContent = displayContent;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700559 mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId());
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700560
561 Rect bounds = null;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700562 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwale3797c222015-10-27 14:21:58 -0700563 if (mStackId == DOCKED_STACK_ID
564 || (dockedStack != null && StackId.isResizeableByDockedStack(mStackId))) {
565 // The existence of a docked stack affects the size of other static stack created since
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700566 // the docked stack occupies a dedicated region on screen.
567 bounds = new Rect();
568 displayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700569 mTmpRect2.setEmpty();
570 if (dockedStack != null) {
571 dockedStack.getRawBounds(mTmpRect2);
572 }
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800573 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700574 == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
575 getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100576 mDisplayContent.mDividerControllerLocked.getContentWidth(),
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700577 dockedOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700578 }
579
580 updateDisplayInfo(bounds);
581
582 if (mStackId == DOCKED_STACK_ID) {
583 // Attaching a docked stack to the display affects the size of all other static
584 // stacks since the docked stack occupies a dedicated region on screen.
585 // Resize existing static stacks so they are pushed to the side of the docked stack.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700586 resizeNonDockedStacks(!FULLSCREEN, mBounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700587 }
588 }
589
Wale Ogunwale961f4852016-02-01 20:25:54 -0800590 void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800591 if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
592 || mDisplayContent == null) {
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700593 outBounds.set(mBounds);
594 return;
595 }
596
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700597 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700598 if (dockedStack == null) {
599 // Not sure why you are calling this method when there is no docked stack...
600 throw new IllegalStateException(
601 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
602 }
Wale Ogunwale961f4852016-02-01 20:25:54 -0800603 if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700604 // The docked stack is being dismissed, but we caught before it finished being
605 // dismissed. In that case we want to treat it as if it is not occupying any space and
606 // let others occupy the whole display.
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -0800607 mDisplayContent.getLogicalDisplayRect(outBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700608 return;
609 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700610
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700611 final int dockedSide = dockedStack.getDockSide();
612 if (dockedSide == DOCKED_INVALID) {
613 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800614 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700615 outBounds.set(mBounds);
616 return;
617 }
618
619 mDisplayContent.getLogicalDisplayRect(mTmpRect);
620 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800621 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700622 getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100623 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700624
625 }
626
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700627 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700628 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700629 * @param displayRect The bounds of the display the docked stack is on.
630 * @param outBounds Output bounds that should be used for the stack.
631 * @param stackId Id of stack we are calculating the bounds for.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700632 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700633 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
634 * close to the side of the dock.
635 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700636 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800637 private void getStackDockedModeBounds(
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700638 Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
639 boolean dockOnTopOrLeft) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700640 final boolean dockedStack = stackId == DOCKED_STACK_ID;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700641 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700642
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700643 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700644 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800645 if (mService.mDockedStackCreateBounds != null) {
646 outBounds.set(mService.mDockedStackCreateBounds);
647 return;
648 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100649
650 // The initial bounds of the docked stack when it is created about half the screen space
651 // and its bounds can be adjusted after that. The bounds of all other stacks are
652 // adjusted to occupy whatever screen space the docked stack isn't occupying.
653 final DisplayInfo di = mDisplayContent.getDisplayInfo();
654 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
655 mTmpRect2);
656 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100657 di.logicalWidth,
658 di.logicalHeight,
659 dockDividerWidth,
660 mService.mCurConfiguration.orientation == ORIENTATION_PORTRAIT,
661 mTmpRect2).getMiddleTarget().position;
662
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700663 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700664 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100665 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700666 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100667 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700668 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700669 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700670 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100671 outBounds.left = position - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700672 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100673 outBounds.top = position - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700674 }
675 }
676 return;
677 }
678
679 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700680 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700681 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700682 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700683 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700684 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700685 }
686 } else {
687 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700688 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700689 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700690 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700691 }
692 }
Jorim Jaggi08b372f2016-01-27 01:01:06 -0800693 DockedDividerUtils.sanitizeStackBounds(outBounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700694 }
695
696 /** Resizes all non-docked stacks in the system to either fullscreen or the appropriate size
697 * based on the presence of a docked stack.
698 * @param fullscreen If true the stacks will be resized to fullscreen, else they will be
699 * resized to the appropriate size based on the presence of a docked stack.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700700 * @param dockedBounds Bounds of the docked stack.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700701 */
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700702 private void resizeNonDockedStacks(boolean fullscreen, Rect dockedBounds) {
703 // Not using mTmpRect because we are posting the object in a message.
704 final Rect bounds = new Rect();
705 mDisplayContent.getLogicalDisplayRect(bounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700706 if (!fullscreen) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800707 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700708 == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
709 getStackDockedModeBounds(bounds, bounds, FULLSCREEN_WORKSPACE_STACK_ID, dockedBounds,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100710 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700711 }
712
713 final int count = mService.mStackIdToStack.size();
714 for (int i = 0; i < count; i++) {
715 final TaskStack otherStack = mService.mStackIdToStack.valueAt(i);
716 final int otherStackId = otherStack.mStackId;
Wale Ogunwale3856bf72015-11-20 09:36:46 -0800717 if (StackId.isResizeableByDockedStack(otherStackId)
718 && !otherStack.mBounds.equals(bounds)) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700719 mService.mH.sendMessage(
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700720 mService.mH.obtainMessage(RESIZE_STACK, otherStackId,
Wale Ogunwale3856bf72015-11-20 09:36:46 -0800721 1 /*allowResizeInDockedMode*/, fullscreen ? null : bounds));
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700722 }
723 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800724 }
725
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800726 void resetDockedStackToMiddle() {
727 if (mStackId != DOCKED_STACK_ID) {
728 throw new IllegalStateException("Not a docked stack=" + this);
729 }
730
731 mService.mDockedStackCreateBounds = null;
732
733 final Rect bounds = new Rect();
734 getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
735 mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
736 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
737 }
738
Craig Mautnerdc548482014-02-05 13:35:24 -0800739 void detachDisplay() {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800740 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700741
742 boolean doAnotherLayoutPass = false;
Craig Mautnerdc548482014-02-05 13:35:24 -0800743 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700744 final AppTokenList appWindowTokens = mTasks.get(taskNdx).mAppTokens;
745 for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
746 final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
747 for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
Filip Gruszczynskid66af6a2015-08-31 08:57:24 -0700748 // We are in the middle of changing the state of displays/stacks/tasks. We need
749 // to finish that, before we let layout interfere with it.
Filip Gruszczynski49b80af2015-09-24 09:04:26 -0700750 mService.removeWindowLocked(appWindows.get(winNdx));
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700751 doAnotherLayoutPass = true;
752 }
753 }
Craig Mautnerdc548482014-02-05 13:35:24 -0800754 }
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700755 if (doAnotherLayoutPass) {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700756 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700757 }
758
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700759 if (mStackId == DOCKED_STACK_ID) {
760 // Docked stack was detached from the display, so we no longer need to restrict the
761 // region of the screen other static stacks occupy. Go ahead and make them fullscreen.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700762 resizeNonDockedStacks(FULLSCREEN, null);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700763 }
764
Craig Mautner00a66752015-03-23 14:00:47 -0700765 close();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700766 }
767
Craig Mautner05d29032013-05-03 13:40:13 -0700768 void resetAnimationBackgroundAnimator() {
769 mAnimationBackgroundAnimator = null;
770 mAnimationBackgroundSurface.hide();
771 }
772
Craig Mautner05d29032013-05-03 13:40:13 -0700773 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
774 int animLayer = winAnimator.mAnimLayer;
775 if (mAnimationBackgroundAnimator == null
776 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
777 mAnimationBackgroundAnimator = winAnimator;
778 animLayer = mService.adjustAnimationBackground(winAnimator);
779 mAnimationBackgroundSurface.show(animLayer - WindowManagerService.LAYER_OFFSET_DIM,
780 ((color >> 24) & 0xff) / 255f, 0);
781 }
782 }
783
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800784 void switchUser() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700785 int top = mTasks.size();
786 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
787 Task task = mTasks.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700788 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700789 mTasks.remove(taskNdx);
790 mTasks.add(task);
791 --top;
792 }
793 }
794 }
795
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800796 void close() {
Craig Mautner00a66752015-03-23 14:00:47 -0700797 if (mAnimationBackgroundSurface != null) {
798 mAnimationBackgroundSurface.destroySurface();
799 mAnimationBackgroundSurface = null;
800 }
Filip Gruszczynski26ed2652015-08-10 11:02:53 -0700801 mDisplayContent = null;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800802 }
803
Craig Mautner00af9fe2013-03-25 09:13:41 -0700804 public void dump(String prefix, PrintWriter pw) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800805 pw.println(prefix + "mStackId=" + mStackId);
806 pw.println(prefix + "mDeferDetach=" + mDeferDetach);
807 pw.println(prefix + "mFullscreen=" + mFullscreen);
808 pw.println(prefix + "mBounds=" + mBounds.toShortString());
809 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; taskNdx--) {
810 mTasks.get(taskNdx).dump(prefix + " ", pw);
Craig Mautner00af9fe2013-03-25 09:13:41 -0700811 }
Craig Mautner05d29032013-05-03 13:40:13 -0700812 if (mAnimationBackgroundSurface.isDimming()) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -0800813 pw.println(prefix + "mWindowAnimationBackgroundSurface:");
Craig Mautner05d29032013-05-03 13:40:13 -0700814 mAnimationBackgroundSurface.printTo(prefix + " ", pw);
815 }
Craig Mautnerdc548482014-02-05 13:35:24 -0800816 if (!mExitingAppTokens.isEmpty()) {
817 pw.println();
818 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700819 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -0800820 WindowToken token = mExitingAppTokens.get(i);
821 pw.print(" Exiting App #"); pw.print(i);
822 pw.print(' '); pw.print(token);
823 pw.println(':');
824 token.dump(pw, " ");
825 }
826 }
Craig Mautner00af9fe2013-03-25 09:13:41 -0700827 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700828
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700829 /** Fullscreen status of the stack without adjusting for other factors in the system like
830 * visibility of docked stack.
831 * Most callers should be using {@link #isFullscreen} as it take into consideration other
832 * system factors. */
833 boolean getRawFullscreen() {
834 return mFullscreen;
835 }
836
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700837 @Override
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700838 public boolean isFullscreen() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700839 if (useCurrentBounds()) {
840 return mFullscreen;
841 }
842 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
843 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
844 // system.
845 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700846 }
847
848 @Override
849 public DisplayInfo getDisplayInfo() {
850 return mDisplayContent.getDisplayInfo();
851 }
852
853 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700854 public String toString() {
855 return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
856 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700857
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700858 @Override
859 public String toShortString() {
860 return "Stack=" + mStackId;
861 }
862
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700863 /**
Chong Zhangc806d902015-11-30 09:44:27 -0800864 * For docked workspace (or workspace that's side-by-side to the docked), provides
865 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700866 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700867 int getDockSide() {
Jorim Jaggi737af722015-12-31 10:42:27 +0100868 return getDockSide(mBounds);
869 }
870
871 int getDockSide(Rect bounds) {
Chong Zhangc806d902015-11-30 09:44:27 -0800872 if (mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId)) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700873 return DOCKED_INVALID;
874 }
875 if (mDisplayContent == null) {
876 return DOCKED_INVALID;
877 }
878 mDisplayContent.getLogicalDisplayRect(mTmpRect);
879 final int orientation = mService.mCurConfiguration.orientation;
880 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
881 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi067e8172016-02-03 18:24:12 -0800882 if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700883 return DOCKED_TOP;
884 } else {
885 return DOCKED_BOTTOM;
886 }
887 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
888 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi067e8172016-02-03 18:24:12 -0800889 if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -0700890 return DOCKED_LEFT;
891 } else {
892 return DOCKED_RIGHT;
893 }
894 } else {
895 return DOCKED_INVALID;
896 }
897 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700898
899 boolean isVisibleLocked() {
Chong Zhang75b37202015-12-04 14:16:36 -0800900 final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded();
901 if (keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -0800902 // The keyguard is showing and the stack shouldn't show on top of the keyguard.
Wale Ogunwale961f4852016-02-01 20:25:54 -0800903 return false;
Chong Zhang75b37202015-12-04 14:16:36 -0800904 }
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -0800905
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -0700906 for (int i = mTasks.size() - 1; i >= 0; i--) {
907 Task task = mTasks.get(i);
908 for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
909 if (!task.mAppTokens.get(j).hidden) {
910 return true;
911 }
912 }
913 }
914 return false;
915 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800916
Wale Ogunwalece144522016-02-05 22:51:01 -0800917 boolean isDragResizing() {
918 return mDragResizing;
919 }
920
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800921 @Override // AnimatesBounds
922 public boolean setSize(Rect bounds) {
923 synchronized (mService.mWindowMap) {
924 if (mDisplayContent == null) {
925 return false;
926 }
927 }
928 try {
929 mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false);
930 } catch (RemoteException e) {
931 }
932 return true;
933 }
934
935 @Override // AnimatesBounds
Wale Ogunwalece144522016-02-05 22:51:01 -0800936 public void onAnimationStart() {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800937 synchronized (mService.mWindowMap) {
Wale Ogunwalece144522016-02-05 22:51:01 -0800938 mDragResizing = true;
939 }
940 }
941
942 @Override // AnimatesBounds
943 public void onAnimationEnd() {
944 synchronized (mService.mWindowMap) {
945 mDragResizing = false;
946 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -0800947 }
948 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -0800949
950 @Override
951 public void moveToFullscreen() {
952 try {
953 mService.mActivityManager.moveTasksToFullscreenStack(mStackId, true);
954 } catch (RemoteException e) {
955 e.printStackTrace();
956 }
957 }
958
959 @Override
960 public void getFullScreenBounds(Rect bounds) {
961 getDisplayContent().getContentRect(bounds);
962 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800963}