blob: 223e03ad4cc48ba26259558efa19de817bb88340 [file] [log] [blame]
Craig Mautnerb1fd65c02013-02-05 13:34:57 -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 static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21import static android.app.ActivityManager.StackId.HOME_STACK_ID;
Chong Zhangb15758a2015-11-17 12:12:03 -080022import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
Wale Ogunwale1ed0d892015-09-28 13:27:44 -070023import static android.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080024import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
25import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
26import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
Wale Ogunwale1ed0d892015-09-28 13:27:44 -070027import static com.android.server.wm.WindowManagerService.H.RESIZE_TASK;
Chong Zhangc806d902015-11-30 09:44:27 -080028import static com.android.server.wm.WindowManagerService.H.SHOW_NON_RESIZEABLE_DOCK_TOAST;
29import static android.view.WindowManager.DOCKED_INVALID;
30import static android.view.WindowManager.DOCKED_LEFT;
31import static android.view.WindowManager.DOCKED_RIGHT;
32import static android.view.WindowManager.DOCKED_TOP;
Wale Ogunwale99db1862015-10-23 20:08:22 -070033
Wale Ogunwale3797c222015-10-27 14:21:58 -070034import android.app.ActivityManager.StackId;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070035import android.content.res.Configuration;
36import android.graphics.Rect;
Craig Mautner2c2549c2013-11-12 08:31:15 -080037import android.util.EventLog;
Craig Mautner42bf39e2014-02-21 16:46:22 -080038import android.util.Slog;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070039import android.view.DisplayInfo;
40import android.view.Surface;
41
Craig Mautnere3119b72015-01-20 15:02:36 -080042import com.android.server.EventLogTags;
Craig Mautner2c2549c2013-11-12 08:31:15 -080043
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070044import java.io.PrintWriter;
45import java.util.ArrayList;
46
47class Task implements DimLayer.DimLayerUser {
Wale Ogunwale2cc92f52015-09-09 13:12:10 -070048 // Return value from {@link setBounds} indicating no change was made to the Task bounds.
49 static final int BOUNDS_CHANGE_NONE = 0;
50 // Return value from {@link setBounds} indicating the position of the Task bounds changed.
51 static final int BOUNDS_CHANGE_POSITION = 1;
52 // Return value from {@link setBounds} indicating the size of the Task bounds changed.
53 static final int BOUNDS_CHANGE_SIZE = 1 << 1;
54
Craig Mautnerc00204b2013-03-05 15:02:14 -080055 TaskStack mStack;
Craig Mautner05d6272ba2013-02-11 09:39:27 -080056 final AppTokenList mAppTokens = new AppTokenList();
Craig Mautner83162a92015-01-26 14:43:30 -080057 final int mTaskId;
Craig Mautnerac6f8432013-07-17 13:24:59 -070058 final int mUserId;
Craig Mautner9ef471f2014-02-07 13:11:47 -080059 boolean mDeferRemoval = false;
Craig Mautnere3119b72015-01-20 15:02:36 -080060 final WindowManagerService mService;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080061
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070062 // Content limits relative to the DisplayContent this sits in.
63 private Rect mBounds = new Rect();
Jorim Jaggi0429f352015-12-22 16:29:16 +010064 final Rect mPreparedFrozenBounds = new Rect();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070065
Jorim Jaggidc249c42015-12-15 14:57:31 -080066 // Bounds used to calculate the insets.
67 private final Rect mTempInsetBounds = new Rect();
68
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070069 // Device rotation as of the last time {@link #mBounds} was set.
70 int mRotation;
71
72 // Whether mBounds is fullscreen
73 private boolean mFullscreen = true;
74
75 // Contains configurations settings that are different from the global configuration due to
76 // stack specific operations. E.g. {@link #setBounds}.
77 Configuration mOverrideConfig;
78
79 // For comparison with DisplayContent bounds.
80 private Rect mTmpRect = new Rect();
81 // For handling display rotations.
82 private Rect mTmpRect2 = new Rect();
83
Chong Zhangb15758a2015-11-17 12:12:03 -080084 // Whether the task is resizeable
85 private boolean mResizeable;
86
Chong Zhangc806d902015-11-30 09:44:27 -080087 // Whether we need to show toast about the app being non-resizeable when it becomes visible.
88 // This flag is set when a non-resizeable task is docked (or side-by-side). It's cleared
89 // after we show the toast.
90 private boolean mShowNonResizeableDockToast;
91
Chong Zhang3005e752015-09-18 18:46:28 -070092 // Whether the task is currently being drag-resized
93 private boolean mDragResizing;
94
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070095 Task(int taskId, TaskStack stack, int userId, WindowManagerService service, Rect bounds,
96 Configuration config) {
Craig Mautner83162a92015-01-26 14:43:30 -080097 mTaskId = taskId;
Craig Mautnerc00204b2013-03-05 15:02:14 -080098 mStack = stack;
Craig Mautnerac6f8432013-07-17 13:24:59 -070099 mUserId = userId;
Craig Mautnere3119b72015-01-20 15:02:36 -0800100 mService = service;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700101 setBounds(bounds, config);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800102 }
103
104 DisplayContent getDisplayContent() {
105 return mStack.getDisplayContent();
106 }
107
Chong Zhangc806d902015-11-30 09:44:27 -0800108 void setShowNonResizeableDockToast() {
109 mShowNonResizeableDockToast = true;
110 }
111
112 void scheduleShowNonResizeableDockToastIfNeeded() {
113 if (!mShowNonResizeableDockToast) {
114 return;
115 }
116 final DisplayContent displayContent = mStack.getDisplayContent();
117 // If docked stack is not yet visible, we don't want to show the toast yet,
118 // since we need the visible rect of the docked task to position the toast.
119 if (displayContent == null || displayContent.getDockedStackLocked() == null) {
120 return;
121 }
122
123 mShowNonResizeableDockToast = false;
124
125 final int dockSide = mStack.getDockSide();
126 int xOffset = 0;
127 int yOffset = 0;
128 if (dockSide != DOCKED_INVALID) {
129 mStack.getBounds(mTmpRect);
130 displayContent.getLogicalDisplayRect(mTmpRect2);
131
132 if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
133 xOffset = mTmpRect.centerX() - mTmpRect2.centerX();
134 } else if (dockSide == DOCKED_TOP) {
135 // We don't adjust for DOCKED_BOTTOM case since it's already at the bottom.
136 yOffset = mTmpRect2.bottom - mTmpRect.bottom;
137 }
138 mService.mH.obtainMessage(
139 SHOW_NON_RESIZEABLE_DOCK_TOAST, xOffset, yOffset).sendToTarget();
140 }
141 }
142
Craig Mautnerc00204b2013-03-05 15:02:14 -0800143 void addAppToken(int addPos, AppWindowToken wtoken) {
Craig Mautner42bf39e2014-02-21 16:46:22 -0800144 final int lastPos = mAppTokens.size();
Craig Mautner83162a92015-01-26 14:43:30 -0800145 if (addPos >= lastPos) {
146 addPos = lastPos;
147 } else {
148 for (int pos = 0; pos < lastPos && pos < addPos; ++pos) {
149 if (mAppTokens.get(pos).removed) {
150 // addPos assumes removed tokens are actually gone.
151 ++addPos;
152 }
Craig Mautner01f79cf2014-08-27 09:56:02 -0700153 }
Craig Mautner42bf39e2014-02-21 16:46:22 -0800154 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800155 mAppTokens.add(addPos, wtoken);
Craig Mautner83162a92015-01-26 14:43:30 -0800156 wtoken.mTask = this;
Craig Mautner42bf39e2014-02-21 16:46:22 -0800157 mDeferRemoval = false;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800158 }
159
Craig Mautnere3119b72015-01-20 15:02:36 -0800160 void removeLocked() {
161 if (!mAppTokens.isEmpty() && mStack.isAnimating()) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800162 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: deferring removing taskId=" + mTaskId);
Craig Mautnere3119b72015-01-20 15:02:36 -0800163 mDeferRemoval = true;
164 return;
165 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800166 if (DEBUG_STACK) Slog.i(TAG_WM, "removeTask: removing taskId=" + mTaskId);
Craig Mautner83162a92015-01-26 14:43:30 -0800167 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeTask");
Craig Mautnere3119b72015-01-20 15:02:36 -0800168 mDeferRemoval = false;
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700169 DisplayContent content = getDisplayContent();
170 if (content != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800171 content.mDimLayerController.removeDimLayerUser(this);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700172 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800173 mStack.removeTask(this);
Craig Mautner83162a92015-01-26 14:43:30 -0800174 mService.mTaskIdToTask.delete(mTaskId);
Craig Mautnere3119b72015-01-20 15:02:36 -0800175 }
176
Wale Ogunwale53a29a92015-02-23 15:42:52 -0800177 void moveTaskToStack(TaskStack stack, boolean toTop) {
178 if (stack == mStack) {
179 return;
180 }
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800181 if (DEBUG_STACK) Slog.i(TAG_WM, "moveTaskToStack: removing taskId=" + mTaskId
Wale Ogunwale53a29a92015-02-23 15:42:52 -0800182 + " from stack=" + mStack);
Wale Ogunwale000957c2015-04-03 08:19:12 -0700183 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
Wale Ogunwale53a29a92015-02-23 15:42:52 -0800184 if (mStack != null) {
185 mStack.removeTask(this);
186 }
187 stack.addTask(this, toTop);
188 }
189
Wale Ogunwale935e5022015-11-10 12:36:10 -0800190 void positionTaskInStack(TaskStack stack, int position, Rect bounds, Configuration config) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700191 if (mStack != null && stack != mStack) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800192 if (DEBUG_STACK) Slog.i(TAG_WM, "positionTaskInStack: removing taskId=" + mTaskId
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700193 + " from stack=" + mStack);
194 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "moveTask");
195 mStack.removeTask(this);
196 }
197 stack.positionTask(this, position, showForAllUsers());
Wale Ogunwale935e5022015-11-10 12:36:10 -0800198 setBounds(bounds, config);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700199 }
200
Craig Mautnerc00204b2013-03-05 15:02:14 -0800201 boolean removeAppToken(AppWindowToken wtoken) {
Craig Mautner42bf39e2014-02-21 16:46:22 -0800202 boolean removed = mAppTokens.remove(wtoken);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800203 if (mAppTokens.size() == 0) {
Jorim Jaggi0429f352015-12-22 16:29:16 +0100204 EventLog.writeEvent(EventLogTags.WM_TASK_REMOVED, mTaskId, "removeAppToken: last token");
Craig Mautnere3119b72015-01-20 15:02:36 -0800205 if (mDeferRemoval) {
206 removeLocked();
207 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800208 }
Craig Mautner83162a92015-01-26 14:43:30 -0800209 wtoken.mTask = null;
210 /* Leave mTaskId for now, it might be useful for debug
211 wtoken.mTaskId = -1;
212 */
Craig Mautner42bf39e2014-02-21 16:46:22 -0800213 return removed;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800214 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800215
Craig Mautnercbd84af2014-10-22 13:21:22 -0700216 void setSendingToBottom(boolean toBottom) {
217 for (int appTokenNdx = 0; appTokenNdx < mAppTokens.size(); appTokenNdx++) {
218 mAppTokens.get(appTokenNdx).sendingToBottom = toBottom;
219 }
220 }
221
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700222 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700223 int setBounds(Rect bounds, Configuration config) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700224 if (config == null) {
225 config = Configuration.EMPTY;
226 }
227 if (bounds == null && !Configuration.EMPTY.equals(config)) {
228 throw new IllegalArgumentException("null bounds but non empty configuration: "
229 + config);
230 }
231 if (bounds != null && Configuration.EMPTY.equals(config)) {
232 throw new IllegalArgumentException("non null bounds, but empty configuration");
233 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700234 boolean oldFullscreen = mFullscreen;
235 int rotation = Surface.ROTATION_0;
236 final DisplayContent displayContent = mStack.getDisplayContent();
237 if (displayContent != null) {
238 displayContent.getLogicalDisplayRect(mTmpRect);
239 rotation = displayContent.getDisplayInfo().rotation;
240 if (bounds == null) {
241 bounds = mTmpRect;
242 mFullscreen = true;
243 } else {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700244 mFullscreen = mTmpRect.equals(bounds);
245 }
246 }
247
248 if (bounds == null) {
249 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700250 return BOUNDS_CHANGE_NONE;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700251 }
252 if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700253 return BOUNDS_CHANGE_NONE;
254 }
255
256 int boundsChange = BOUNDS_CHANGE_NONE;
Chong Zhang48a87a52015-12-03 15:36:21 -0800257 if (mBounds.left != bounds.left || mBounds.top != bounds.top) {
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700258 boundsChange |= BOUNDS_CHANGE_POSITION;
259 }
260 if (mBounds.width() != bounds.width() || mBounds.height() != bounds.height()) {
261 boundsChange |= BOUNDS_CHANGE_SIZE;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700262 }
263
264 mBounds.set(bounds);
265 mRotation = rotation;
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700266 if (displayContent != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800267 displayContent.mDimLayerController.updateDimLayer(this);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700268 }
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700269 mOverrideConfig = mFullscreen ? Configuration.EMPTY : config;
Wale Ogunwale2cc92f52015-09-09 13:12:10 -0700270 return boundsChange;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700271 }
272
Jorim Jaggidc249c42015-12-15 14:57:31 -0800273 /**
274 * Sets the bounds used to calculate the insets. See
275 * {@link android.app.IActivityManager#resizeDockedStack} why this is needed.
276 */
277 void setTempInsetBounds(Rect tempInsetBounds) {
278 if (tempInsetBounds != null) {
279 mTempInsetBounds.set(tempInsetBounds);
280 } else {
281 mTempInsetBounds.setEmpty();
282 }
283 }
284
285 /**
286 * Gets the bounds used to calculate the insets. See
287 * {@link android.app.IActivityManager#resizeDockedStack} why this is needed.
288 */
289 void getTempInsetBounds(Rect out) {
290 out.set(mTempInsetBounds);
291 }
292
Chong Zhangb15758a2015-11-17 12:12:03 -0800293 void setResizeable(boolean resizeable) {
294 mResizeable = resizeable;
295 }
296
297 boolean isResizeable() {
298 return mResizeable;
299 }
300
Chong Zhang87b21722015-09-21 15:39:51 -0700301 boolean resizeLocked(Rect bounds, Configuration configuration, boolean forced) {
Chong Zhang3005e752015-09-18 18:46:28 -0700302 int boundsChanged = setBounds(bounds, configuration);
Chong Zhang87b21722015-09-21 15:39:51 -0700303 if (forced) {
Chong Zhang3005e752015-09-18 18:46:28 -0700304 boundsChanged |= BOUNDS_CHANGE_SIZE;
Chong Zhang3005e752015-09-18 18:46:28 -0700305 }
306 if (boundsChanged == BOUNDS_CHANGE_NONE) {
307 return false;
308 }
309 if ((boundsChanged & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
310 resizeWindows();
Chong Zhangbd0d9372015-12-28 15:18:29 -0800311 } else {
312 moveWindows();
Chong Zhang3005e752015-09-18 18:46:28 -0700313 }
314 return true;
315 }
316
Jorim Jaggi0429f352015-12-22 16:29:16 +0100317 /**
318 * Prepares the task bounds to be frozen with the current size. See
319 * {@link AppWindowToken#freezeBounds}.
320 */
321 void prepareFreezingBounds() {
322 mPreparedFrozenBounds.set(mBounds);
323 }
324
Chong Zhangb15758a2015-11-17 12:12:03 -0800325 boolean scrollLocked(Rect bounds) {
326 // shift the task bound if it doesn't fully cover the stack area
327 mStack.getDimBounds(mTmpRect);
328 if (mService.mCurConfiguration.orientation == ORIENTATION_LANDSCAPE) {
329 if (bounds.left > mTmpRect.left) {
330 bounds.left = mTmpRect.left;
331 bounds.right = mTmpRect.left + mBounds.width();
332 } else if (bounds.right < mTmpRect.right) {
333 bounds.left = mTmpRect.right - mBounds.width();
334 bounds.right = mTmpRect.right;
335 }
336 } else {
337 if (bounds.top > mTmpRect.top) {
338 bounds.top = mTmpRect.top;
339 bounds.bottom = mTmpRect.top + mBounds.height();
340 } else if (bounds.bottom < mTmpRect.bottom) {
341 bounds.top = mTmpRect.bottom - mBounds.height();
342 bounds.bottom = mTmpRect.bottom;
343 }
344 }
345
346 if (bounds.equals(mBounds)) {
347 return false;
348 }
349 // Normal setBounds() does not allow non-null bounds for fullscreen apps.
350 // We only change bounds for the scrolling case without change it size,
351 // on resizing path we should still want the validation.
352 mBounds.set(bounds);
353 for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
354 final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
355 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
356 final WindowState win = windows.get(winNdx);
357 win.mXOffset = bounds.left;
358 win.mYOffset = bounds.top;
359 }
360 }
361 return true;
362 }
363
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700364 /** Return true if the current bound can get outputted to the rest of the system as-is. */
365 private boolean useCurrentBounds() {
366 final DisplayContent displayContent = mStack.getDisplayContent();
367 if (mFullscreen
Wale Ogunwale3797c222015-10-27 14:21:58 -0700368 || !StackId.isTaskResizeableByDockedStack(mStack.mStackId)
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700369 || displayContent == null
370 || displayContent.getDockedStackLocked() != null) {
371 return true;
372 }
373 return false;
374 }
375
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800376 /** Original bounds of the task if applicable, otherwise fullscreen rect. */
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700377 public void getBounds(Rect out) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700378 if (useCurrentBounds()) {
379 // No need to adjust the output bounds if fullscreen or the docked stack is visible
380 // since it is already what we want to represent to the rest of the system.
381 out.set(mBounds);
382 return;
383 }
384
385 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
386 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
387 // system.
388 mStack.getDisplayContent().getLogicalDisplayRect(out);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700389 }
390
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800391 /**
392 * Calculate the maximum visible area of this task. If the task has only one app,
393 * the result will be visible frame of that app. If the task has more than one apps,
394 * we search from top down if the next app got different visible area.
395 *
396 * This effort is to handle the case where some task (eg. GMail composer) might pop up
397 * a dialog that's different in size from the activity below, in which case we should
398 * be dimming the entire task area behind the dialog.
399 *
400 * @param out Rect containing the max visible bounds.
401 * @return true if the task has some visible app windows; false otherwise.
402 */
403 boolean getMaxVisibleBounds(Rect out) {
404 boolean foundTop = false;
405 for (int i = mAppTokens.size() - 1; i >= 0; i--) {
Chong Zhangd8ceb852015-11-11 14:53:41 -0800406 final AppWindowToken token = mAppTokens.get(i);
407 // skip hidden (or about to hide) apps
408 if (token.mIsExiting || token.clientHidden || token.hiddenRequested) {
409 continue;
410 }
411 final WindowState win = token.findMainWindow();
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800412 if (win == null) {
413 continue;
414 }
415 if (!foundTop) {
416 out.set(win.mVisibleFrame);
417 foundTop = true;
418 continue;
419 }
420 if (win.mVisibleFrame.left < out.left) {
421 out.left = win.mVisibleFrame.left;
422 }
423 if (win.mVisibleFrame.top < out.top) {
424 out.top = win.mVisibleFrame.top;
425 }
426 if (win.mVisibleFrame.right > out.right) {
427 out.right = win.mVisibleFrame.right;
428 }
429 if (win.mVisibleFrame.bottom > out.bottom) {
430 out.bottom = win.mVisibleFrame.bottom;
431 }
432 }
433 return foundTop;
434 }
435
436 /** Bounds of the task to be used for dimming, as well as touch related tests. */
437 @Override
438 public void getDimBounds(Rect out) {
439 if (useCurrentBounds()) {
440 if (inFreeformWorkspace() && getMaxVisibleBounds(out)) {
441 return;
442 }
443
444 out.set(mBounds);
445 return;
446 }
447
448 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
449 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
450 // system.
451 mStack.getDisplayContent().getLogicalDisplayRect(out);
452 }
453
Chong Zhang3005e752015-09-18 18:46:28 -0700454 void setDragResizing(boolean dragResizing) {
Chong Zhang3005e752015-09-18 18:46:28 -0700455 mDragResizing = dragResizing;
456 }
457
458 boolean isDragResizing() {
459 return mDragResizing;
460 }
461
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700462 void updateDisplayInfo(final DisplayContent displayContent) {
463 if (displayContent == null) {
464 return;
465 }
466 if (mFullscreen) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700467 setBounds(null, Configuration.EMPTY);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700468 return;
469 }
470 final int newRotation = displayContent.getDisplayInfo().rotation;
471 if (mRotation == newRotation) {
472 return;
473 }
474
475 // Device rotation changed. We don't want the task to move around on the screen when
476 // this happens, so update the task bounds so it stays in the same place.
Wale Ogunwale94744212015-09-21 19:01:47 -0700477 mTmpRect2.set(mBounds);
478 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
Wale Ogunwale1ed0d892015-09-28 13:27:44 -0700479 if (setBounds(mTmpRect2, mOverrideConfig) != BOUNDS_CHANGE_NONE) {
480 // Post message to inform activity manager of the bounds change simulating
481 // a one-way call. We do this to prevent a deadlock between window manager
Filip Gruszczynski44bc4da2015-10-03 13:59:49 -0700482 // lock and activity manager lock been held. Only tasks within the freeform stack
483 // are resizeable independently of their stack resizing.
484 if (mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
485 mService.mH.sendMessage(mService.mH.obtainMessage(
486 RESIZE_TASK, mTaskId, RESIZE_MODE_SYSTEM_SCREEN_ROTATION, mBounds));
487 }
Wale Ogunwale1ed0d892015-09-28 13:27:44 -0700488 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700489 }
490
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700491 void resizeWindows() {
492 final ArrayList<WindowState> resizingWindows = mService.mResizingWindows;
493 for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
494 final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
495 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
496 final WindowState win = windows.get(winNdx);
497 if (!resizingWindows.contains(win)) {
Chong Zhangbd0d9372015-12-28 15:18:29 -0800498 if (DEBUG_RESIZE) Slog.d(TAG_WM, "resizeWindows: Resizing " + win);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700499 resizingWindows.add(win);
500 }
501 }
502 }
503 }
504
Chong Zhangbd0d9372015-12-28 15:18:29 -0800505 void moveWindows() {
506 for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
507 final ArrayList<WindowState> windows = mAppTokens.get(activityNdx).allAppWindows;
508 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
509 final WindowState win = windows.get(winNdx);
510 if (DEBUG_RESIZE) Slog.d(TAG_WM, "moveWindows: Moving " + win);
511 win.mMovedByResize = true;
512 }
513 }
514 }
515
Winsonc28098f2015-10-30 14:50:19 -0700516 /**
517 * Cancels any running app transitions associated with the task.
518 */
519 void cancelTaskWindowTransition() {
520 for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
521 mAppTokens.get(activityNdx).mAppAnimator.clearAnimation();
522 }
523 }
524
Winson13d30662015-11-06 15:30:29 -0800525 /**
526 * Cancels any running thumbnail transitions associated with the task.
527 */
528 void cancelTaskThumbnailTransition() {
529 for (int activityNdx = mAppTokens.size() - 1; activityNdx >= 0; --activityNdx) {
530 mAppTokens.get(activityNdx).mAppAnimator.clearThumbnail();
531 }
532 }
533
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700534 boolean showForAllUsers() {
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700535 final int tokensCount = mAppTokens.size();
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700536 return (tokensCount != 0) && mAppTokens.get(tokensCount - 1).showForAllUsers;
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700537 }
538
Chong Zhangdb20b5f2015-10-23 14:01:43 -0700539 boolean inHomeStack() {
540 return mStack != null && mStack.mStackId == HOME_STACK_ID;
541 }
542
Chong Zhang09b21ef2015-09-14 10:20:21 -0700543 boolean inFreeformWorkspace() {
544 return mStack != null && mStack.mStackId == FREEFORM_WORKSPACE_STACK_ID;
545 }
546
Filip Gruszczynski955b2fc2015-10-15 14:46:07 -0700547 boolean inDockedWorkspace() {
548 return mStack != null && mStack.mStackId == DOCKED_STACK_ID;
549 }
550
Chong Zhangb15758a2015-11-17 12:12:03 -0800551 boolean isResizeableByDockedStack() {
552 return mStack != null && getDisplayContent().getDockedStackLocked() != null &&
553 StackId.isTaskResizeableByDockedStack(mStack.mStackId);
554 }
555
556 /**
557 * Whether the task should be treated as if it's docked. Returns true if the task
558 * is currently in docked workspace, or it's side-by-side to a docked task.
559 */
560 boolean isDockedInEffect() {
561 return inDockedWorkspace() || isResizeableByDockedStack();
562 }
563
Chong Zhangd8ceb852015-11-11 14:53:41 -0800564 WindowState getTopVisibleAppMainWindow() {
565 final AppWindowToken token = getTopVisibleAppToken();
566 return token != null ? token.findMainWindow() : null;
Chong Zhang9184ec62015-09-24 12:32:21 -0700567 }
568
Chong Zhangd8ceb852015-11-11 14:53:41 -0800569 AppWindowToken getTopVisibleAppToken() {
570 for (int i = mAppTokens.size() - 1; i >= 0; i--) {
571 final AppWindowToken token = mAppTokens.get(i);
572 // skip hidden (or about to hide) apps
573 if (!token.mIsExiting && !token.clientHidden && !token.hiddenRequested) {
574 return token;
575 }
576 }
577 return null;
Chong Zhangbef461f2015-10-27 11:38:24 -0700578 }
579
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800580 @Override
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700581 public boolean isFullscreen() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700582 if (useCurrentBounds()) {
583 return mFullscreen;
584 }
585 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
586 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
587 // system.
588 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700589 }
590
591 @Override
592 public DisplayInfo getDisplayInfo() {
593 return mStack.getDisplayContent().getDisplayInfo();
594 }
595
596 @Override
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800597 public String toString() {
Craig Mautner83162a92015-01-26 14:43:30 -0800598 return "{taskId=" + mTaskId + " appTokens=" + mAppTokens + " mdr=" + mDeferRemoval + "}";
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800599 }
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700600
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700601 @Override
602 public String toShortString() {
603 return "Task=" + mTaskId;
604 }
605
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700606 public void printTo(String prefix, PrintWriter pw) {
Wale Ogunwale56b88af2015-12-01 07:21:59 -0800607 pw.print(prefix); pw.print("taskId="); pw.println(mTaskId);
608 pw.print(prefix + prefix); pw.print("mFullscreen="); pw.println(mFullscreen);
609 pw.print(prefix + prefix); pw.print("mBounds="); pw.println(mBounds.toShortString());
610 pw.print(prefix + prefix); pw.print("mdr="); pw.println(mDeferRemoval);
611 pw.print(prefix + prefix); pw.print("appTokens="); pw.println(mAppTokens);
Jorim Jaggi0429f352015-12-22 16:29:16 +0100612 pw.print(prefix + prefix); pw.print("mTempInsetBounds="); pw.println(mTempInsetBounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700613 }
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800614}