blob: 0225c9b4105f5691d7fbbaa033fb6ca309158733 [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;
Wale Ogunwale480dca02016-02-06 13:58:29 -080041import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Jorim Jaggid434dcb2016-01-06 17:18:44 +010042import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010043import static android.view.WindowManager.DOCKED_BOTTOM;
44import static android.view.WindowManager.DOCKED_INVALID;
45import static android.view.WindowManager.DOCKED_LEFT;
46import static android.view.WindowManager.DOCKED_RIGHT;
47import static android.view.WindowManager.DOCKED_TOP;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080048import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_TASK_MOVEMENT;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010049import static com.android.server.wm.WindowManagerService.H.RESIZE_STACK;
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -080050import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi61f39a72015-10-29 16:54:18 +010051
Filip Gruszczynski84fa3352016-01-25 16:28:49 -080052public class TaskStack implements DimLayer.DimLayerUser,
53 BoundsAnimationController.AnimateBoundsUser {
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -070054
55 // If the stack should be resized to fullscreen.
56 private static final boolean FULLSCREEN = true;
57
Chong Zhangbaba7832016-03-24 10:21:26 -070058 // When we have a top-bottom split screen, we shift the bottom stack up to accommodate
59 // the IME window. The static flag below controls whether to run animation when the
60 // IME window goes away.
61 private static final boolean ANIMATE_IME_GOING_AWAY = false;
62
Craig Mautner00af9fe2013-03-25 09:13:41 -070063 /** Unique identifier */
Craig Mautnerc00204b2013-03-05 15:02:14 -080064 final int mStackId;
Craig Mautner00af9fe2013-03-25 09:13:41 -070065
Craig Mautner05d29032013-05-03 13:40:13 -070066 /** The service */
67 private final WindowManagerService mService;
68
Craig Mautner00af9fe2013-03-25 09:13:41 -070069 /** The display this stack sits under. */
Craig Mautnerdf88d732014-01-27 09:21:32 -080070 private DisplayContent mDisplayContent;
Craig Mautner00af9fe2013-03-25 09:13:41 -070071
72 /** The Tasks that define this stack. Oldest Tasks are at the bottom. The ordering must match
73 * mTaskHistory in the ActivityStack with the same mStackId */
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070074 private final ArrayList<Task> mTasks = new ArrayList<>();
Craig Mautner00af9fe2013-03-25 09:13:41 -070075
Craig Mautnerb660b9d2014-02-13 10:59:16 -080076 /** For comparison with DisplayContent bounds. */
77 private Rect mTmpRect = new Rect();
Wale Ogunwalee45899a2015-10-01 11:30:34 -070078 private Rect mTmpRect2 = new Rect();
Craig Mautnerb660b9d2014-02-13 10:59:16 -080079
80 /** Content limits relative to the DisplayContent this sits in. */
81 private Rect mBounds = new Rect();
82
Chong Zhangb816b862016-01-25 12:01:12 -080083 /** Stack bounds adjusted to screen content area (taking into account IM windows, etc.) */
84 private final Rect mAdjustedBounds = new Rect();
85
Craig Mautnerb660b9d2014-02-13 10:59:16 -080086 /** Whether mBounds is fullscreen */
87 private boolean mFullscreen = true;
Craig Mautnerc00204b2013-03-05 15:02:14 -080088
Wale Ogunwale94744212015-09-21 19:01:47 -070089 // Device rotation as of the last time {@link #mBounds} was set.
90 int mRotation;
91
Craig Mautner05d29032013-05-03 13:40:13 -070092 /** Support for non-zero {@link android.view.animation.Animation#getBackgroundColor()} */
Craig Mautnerdf88d732014-01-27 09:21:32 -080093 DimLayer mAnimationBackgroundSurface;
Craig Mautner05d29032013-05-03 13:40:13 -070094
95 /** The particular window with an Animation with non-zero background color. */
96 WindowStateAnimator mAnimationBackgroundAnimator;
97
Craig Mautnerdc548482014-02-05 13:35:24 -080098 /** Application tokens that are exiting, but still on screen for animations. */
99 final AppTokenList mExitingAppTokens = new AppTokenList();
100
Craig Mautner95da1082014-02-24 17:54:35 -0800101 /** Detach this stack from its display when animation completes. */
102 boolean mDeferDetach;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800103
104 // Display rotation as of the last time the display information was updated for this stack.
105 private int mLastUpdateDisplayInfoRotation = -1;
106 // Display rotation as of the last time the configuration was updated for this stack.
107 private int mLastConfigChangedRotation = -1;
Craig Mautner95da1082014-02-24 17:54:35 -0800108
Wale Ogunwalece144522016-02-05 22:51:01 -0800109 // Whether the stack and all its tasks is currently being drag-resized
110 private boolean mDragResizing;
111
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800112 private final Rect mLastContentBounds = new Rect();
113 private final Rect mTmpAdjustedBounds = new Rect();
114 private boolean mAdjustedForIme;
Chong Zhangbaba7832016-03-24 10:21:26 -0700115 private boolean mImeGoingAway;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800116 private WindowState mImeWin;
117 private float mMinimizeAmount;
118 private final int mDockedStackMinimizeThickness;
119
Robert Carr0d00c2e2016-02-29 17:45:02 -0800120 // If this is true, the task will be down or upscaled
121 // to perfectly fit the region it would have been cropped
122 // to.
123 private boolean mForceScaleToCrop = false;
124 // By default, movement animations are applied to all
125 // window movement. If this is true, animations will not
126 // be applied within this stack. This is useful for example
127 // if the windows are moving as the result of a stack animation,
128 // in which case a second window animation would cause jitter.
129 private boolean mFreezeMovementAnimations = false;
130
Chong Zhang167bbfac2016-03-31 09:44:34 -0700131 // Temporary storage for the new bounds that should be used after the configuration change.
132 // Will be cleared once the client retrieves the new bounds via getBoundsForNewConfiguration().
133 private final Rect mBoundsAfterRotation = new Rect();
134
Craig Mautnerdf88d732014-01-27 09:21:32 -0800135 TaskStack(WindowManagerService service, int stackId) {
Craig Mautner05d29032013-05-03 13:40:13 -0700136 mService = service;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800137 mStackId = stackId;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800138 mDockedStackMinimizeThickness = service.mContext.getResources().getDimensionPixelSize(
139 com.android.internal.R.dimen.docked_stack_minimize_thickness);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700140 EventLog.writeEvent(EventLogTags.WM_STACK_CREATED, stackId);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800141 }
142
143 DisplayContent getDisplayContent() {
144 return mDisplayContent;
145 }
146
Craig Mautnerd9a22882013-03-16 15:00:36 -0700147 ArrayList<Task> getTasks() {
148 return mTasks;
149 }
150
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700151 /**
152 * Set the bounds of the stack and its containing tasks.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700153 * @param stackBounds New stack bounds. Passing in null sets the bounds to fullscreen.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700154 * @param configs Configuration for individual tasks, keyed by task id.
155 * @param taskBounds Bounds for individual tasks, keyed by task id.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700156 * @return True if the stack bounds was changed.
157 * */
Wale Ogunwalea6e902e2015-09-21 18:37:15 -0700158 boolean setBounds(
Jorim Jaggidc249c42015-12-15 14:57:31 -0800159 Rect stackBounds, SparseArray<Configuration> configs, SparseArray<Rect> taskBounds,
160 SparseArray<Rect> taskTempInsetBounds) {
Jorim Jaggi899327f2016-02-25 20:44:18 -0500161 setBounds(stackBounds);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700162
163 // Update bounds of containing tasks.
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700164 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
165 final Task task = mTasks.get(taskNdx);
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700166 Configuration config = configs.get(task.mTaskId);
167 if (config != null) {
168 Rect bounds = taskBounds.get(task.mTaskId);
Chong Zhang2a88fc32016-01-11 17:14:24 -0800169 if (task.isTwoFingerScrollMode()) {
Chong Zhangb15758a2015-11-17 12:12:03 -0800170 // This is a non-resizeable task that's docked (or side-by-side to the docked
171 // stack). It might have been scrolled previously, and after the stack resizing,
172 // it might no longer fully cover the stack area.
173 // Save the old bounds and re-apply the scroll. This adjusts the bounds to
174 // fit the new stack bounds.
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100175 task.resizeLocked(bounds, config, false /* forced */);
Chong Zhangf66db432016-01-13 10:39:51 -0800176 task.getBounds(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -0800177 task.scrollLocked(mTmpRect);
178 } else {
Jorim Jaggi4846ee32016-01-07 17:39:12 +0100179 task.resizeLocked(bounds, config, false /* forced */);
Jorim Jaggidc249c42015-12-15 14:57:31 -0800180 task.setTempInsetBounds(
181 taskTempInsetBounds != null ? taskTempInsetBounds.get(task.mTaskId)
182 : null);
Chong Zhangb15758a2015-11-17 12:12:03 -0800183 }
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -0700184 } else {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800185 Slog.wtf(TAG_WM, "No config for task: " + task + ", is there a mismatch with AM?");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700186 }
187 }
188 return true;
189 }
190
Jorim Jaggi0429f352015-12-22 16:29:16 +0100191 void prepareFreezingTaskBounds() {
192 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
193 final Task task = mTasks.get(taskNdx);
194 task.prepareFreezingBounds();
195 }
196 }
197
Wale Ogunwaleb4ec0a32015-12-14 10:31:43 -0800198 boolean isFullscreenBounds(Rect bounds) {
199 if (mDisplayContent == null || bounds == null) {
200 return true;
201 }
202 mDisplayContent.getLogicalDisplayRect(mTmpRect);
203 return mTmpRect.equals(bounds);
204 }
205
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800206 /**
207 * Overrides the adjusted bounds, i.e. sets temporary layout bounds which are different from
208 * the normal task bounds.
209 *
210 * @param bounds The adjusted bounds.
211 * @param keepInsets Whether to keep the insets from the original bounds or to calculate new
212 * ones depending on the adjusted bounds.
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700213 * @return true if the adjusted bounds has changed.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800214 */
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700215 private boolean setAdjustedBounds(Rect bounds, boolean keepInsets) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800216 if (mAdjustedBounds.equals(bounds)) {
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700217 return false;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800218 }
219
220 mAdjustedBounds.set(bounds);
221 final boolean adjusted = !mAdjustedBounds.isEmpty();
222 alignTasksToAdjustedBounds(adjusted ? mAdjustedBounds : mBounds,
223 adjusted && keepInsets ? mBounds : null);
224 mDisplayContent.layoutNeeded = true;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700225 return true;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800226 }
227
228 private void alignTasksToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds) {
Chong Zhangb816b862016-01-25 12:01:12 -0800229 if (mFullscreen) {
230 return;
231 }
232 // Update bounds of containing tasks.
233 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
234 final Task task = mTasks.get(taskNdx);
235 if (task.isTwoFingerScrollMode()) {
236 // If we're scrolling we don't care about your bounds or configs,
237 // they should be null as if we were in fullscreen.
238 task.resizeLocked(null, null, false /* forced */);
239 task.getBounds(mTmpRect2);
240 task.scrollLocked(mTmpRect2);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800241 } else if (task.isResizeable() && task.mOverrideConfig != Configuration.EMPTY) {
Chong Zhangb816b862016-01-25 12:01:12 -0800242 task.getBounds(mTmpRect2);
243 mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top);
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800244 task.setTempInsetBounds(tempInsetBounds);
Chong Zhangb816b862016-01-25 12:01:12 -0800245 task.resizeLocked(mTmpRect2, task.mOverrideConfig, false /* forced */);
246 }
247 }
248 }
249
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700250 private boolean setBounds(Rect bounds) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800251 boolean oldFullscreen = mFullscreen;
Wale Ogunwale94744212015-09-21 19:01:47 -0700252 int rotation = Surface.ROTATION_0;
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800253 if (mDisplayContent != null) {
254 mDisplayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwale94744212015-09-21 19:01:47 -0700255 rotation = mDisplayContent.getDisplayInfo().rotation;
Jorim Jaggi067e8172016-02-03 18:24:12 -0800256 mFullscreen = bounds == null;
257 if (mFullscreen) {
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800258 bounds = mTmpRect;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800259 }
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800260 }
261
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800262 if (bounds == null) {
Wale Ogunwale4a02d812015-02-12 23:01:38 -0800263 // Can't set to fullscreen if we don't have a display to get bounds from...
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800264 return false;
265 }
Wale Ogunwale94744212015-09-21 19:01:47 -0700266 if (mBounds.equals(bounds) && oldFullscreen == mFullscreen && mRotation == rotation) {
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800267 return false;
268 }
269
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700270 if (mDisplayContent != null) {
Chong Zhang112eb8c2015-11-02 11:17:00 -0800271 mDisplayContent.mDimLayerController.updateDimLayer(this);
Filip Gruszczynski57b6cce2015-10-06 09:50:51 -0700272 mAnimationBackgroundSurface.setBounds(bounds);
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700273 }
274
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800275 mBounds.set(bounds);
Wale Ogunwale94744212015-09-21 19:01:47 -0700276 mRotation = rotation;
Chong Zhangb816b862016-01-25 12:01:12 -0800277
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800278 updateAdjustedBounds();
Chong Zhangb816b862016-01-25 12:01:12 -0800279
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800280 return true;
281 }
282
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700283 /** Bounds of the stack without adjusting for other factors in the system like visibility
284 * of docked stack.
285 * Most callers should be using {@link #getBounds} as it take into consideration other system
286 * factors. */
287 void getRawBounds(Rect out) {
Craig Mautnerb660b9d2014-02-13 10:59:16 -0800288 out.set(mBounds);
289 }
290
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700291 /** Return true if the current bound can get outputted to the rest of the system as-is. */
292 private boolean useCurrentBounds() {
293 if (mFullscreen
Wale Ogunwale3797c222015-10-27 14:21:58 -0700294 || !StackId.isResizeableByDockedStack(mStackId)
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700295 || mDisplayContent == null
296 || mDisplayContent.getDockedStackLocked() != null) {
297 return true;
298 }
299 return false;
300 }
301
Filip Gruszczynski0689ae92015-10-01 12:30:31 -0700302 public void getBounds(Rect out) {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700303 if (useCurrentBounds()) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800304 // If we're currently adjusting for IME or minimized docked stack, we use the adjusted
305 // bounds; otherwise, no need to adjust the output bounds if fullscreen or the docked
306 // stack is visible since it is already what we want to represent to the rest of the
307 // system.
308 if (!mAdjustedBounds.isEmpty()) {
Chong Zhangb816b862016-01-25 12:01:12 -0800309 out.set(mAdjustedBounds);
310 } else {
311 out.set(mBounds);
312 }
Wale Ogunwalef175e8a2015-09-29 11:07:06 -0700313 return;
314 }
315
316 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
317 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
318 // system.
319 mDisplayContent.getLogicalDisplayRect(out);
320 }
321
Chong Zhang4c9ba52a2015-11-10 18:36:33 -0800322 /** Bounds of the stack with other system factors taken into consideration. */
323 @Override
324 public void getDimBounds(Rect out) {
325 getBounds(out);
326 }
327
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700328 void updateDisplayInfo(Rect bounds) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800329 if (mDisplayContent == null) {
330 return;
331 }
Jorim Jaggi737af722015-12-31 10:42:27 +0100332
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800333 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
334 mTasks.get(taskNdx).updateDisplayInfo(mDisplayContent);
335 }
336 if (bounds != null) {
337 setBounds(bounds);
338 return;
339 } else if (mFullscreen) {
340 setBounds(null);
341 return;
342 }
343
344 mTmpRect2.set(mBounds);
345 final int newRotation = mDisplayContent.getDisplayInfo().rotation;
346 if (mRotation == newRotation) {
347 setBounds(mTmpRect2);
348 } else {
349 mLastUpdateDisplayInfoRotation = newRotation;
Chong Zhang167bbfac2016-03-31 09:44:34 -0700350 updateBoundsAfterRotation(true);
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800351 }
352 }
353
Chong Zhang167bbfac2016-03-31 09:44:34 -0700354 boolean onConfigurationChanged() {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800355 mLastConfigChangedRotation = getDisplayInfo().rotation;
Chong Zhang167bbfac2016-03-31 09:44:34 -0700356 return updateBoundsAfterRotation(false);
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800357 }
358
Chong Zhang167bbfac2016-03-31 09:44:34 -0700359 boolean updateBoundsAfterRotation(boolean scheduleResize) {
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800360 if (mLastConfigChangedRotation != mLastUpdateDisplayInfoRotation) {
361 // We wait for the rotation values after configuration change and display info. update
362 // to be equal before updating the bounds due to rotation change otherwise things might
363 // get out of alignment...
Chong Zhang167bbfac2016-03-31 09:44:34 -0700364 return false;
Filip Gruszczynskidce2d162016-01-12 15:40:13 -0800365 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800366
Jorim Jaggi737af722015-12-31 10:42:27 +0100367 final int newRotation = getDisplayInfo().rotation;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800368
369 if (mRotation == newRotation) {
370 // Nothing to do here if the rotation didn't change
Chong Zhang167bbfac2016-03-31 09:44:34 -0700371 return false;
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -0800372 }
373
Jorim Jaggi737af722015-12-31 10:42:27 +0100374 mDisplayContent.rotateBounds(mRotation, newRotation, mTmpRect2);
375 if (mStackId == DOCKED_STACK_ID) {
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800376 repositionDockedStackAfterRotation(mTmpRect2);
Jorim Jaggi737af722015-12-31 10:42:27 +0100377 snapDockedStackAfterRotation(mTmpRect2);
378 }
379
Chong Zhang167bbfac2016-03-31 09:44:34 -0700380 if (scheduleResize) {
381 // Post message to inform activity manager of the bounds change simulating
382 // a one-way call. We do this to prevent a deadlock between window manager
383 // lock and activity manager lock been held.
384 mService.mH.obtainMessage(RESIZE_STACK, mStackId,
385 0 /*allowResizeInDockedMode*/, mTmpRect2).sendToTarget();
386 } else {
387 mBoundsAfterRotation.set(mTmpRect2);
388 }
389
390 return true;
391 }
392
393 void getBoundsForNewConfiguration(Rect outBounds) {
394 outBounds.set(mBoundsAfterRotation);
395 mBoundsAfterRotation.setEmpty();
Jorim Jaggi737af722015-12-31 10:42:27 +0100396 }
397
398 /**
Jorim Jaggi5060bd82016-02-19 17:12:19 -0800399 * Some dock sides are not allowed by the policy. This method queries the policy and moves
400 * the docked stack around if needed.
401 *
402 * @param inOutBounds the bounds of the docked stack to adjust
403 */
404 private void repositionDockedStackAfterRotation(Rect inOutBounds) {
405 int dockSide = getDockSide(inOutBounds);
406 if (mService.mPolicy.isDockSideAllowed(dockSide)) {
407 return;
408 }
409 mDisplayContent.getLogicalDisplayRect(mTmpRect);
410 dockSide = DockedDividerUtils.invertDockSide(dockSide);
411 switch (dockSide) {
412 case DOCKED_LEFT:
413 int movement = inOutBounds.left;
414 inOutBounds.left -= movement;
415 inOutBounds.right -= movement;
416 break;
417 case DOCKED_RIGHT:
418 movement = mTmpRect.right - inOutBounds.right;
419 inOutBounds.left += movement;
420 inOutBounds.right += movement;
421 break;
422 case DOCKED_TOP:
423 movement = inOutBounds.top;
424 inOutBounds.top -= movement;
425 inOutBounds.bottom -= movement;
426 break;
427 case DOCKED_BOTTOM:
428 movement = mTmpRect.bottom - inOutBounds.bottom;
429 inOutBounds.top += movement;
430 inOutBounds.bottom += movement;
431 break;
432 }
433 }
434
435 /**
Jorim Jaggi737af722015-12-31 10:42:27 +0100436 * Snaps the bounds after rotation to the closest snap target for the docked stack.
437 */
438 private void snapDockedStackAfterRotation(Rect outBounds) {
439
440 // Calculate the current position.
441 final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
442 final int dividerSize = mService.getDefaultDisplayContentLocked()
443 .getDockedDividerController().getContentWidth();
444 final int dockSide = getDockSide(outBounds);
445 final int dividerPosition = DockedDividerUtils.calculatePositionForBounds(outBounds,
446 dockSide, dividerSize);
447 final int displayWidth = mDisplayContent.getDisplayInfo().logicalWidth;
448 final int displayHeight = mDisplayContent.getDisplayInfo().logicalHeight;
449
450 // Snap the position to a target.
451 final int rotation = displayInfo.rotation;
452 final int orientation = mService.mCurConfiguration.orientation;
453 mService.mPolicy.getStableInsetsLw(rotation, displayWidth, displayHeight, outBounds);
454 final DividerSnapAlgorithm algorithm = new DividerSnapAlgorithm(
Jorim Jaggidf012d52016-01-15 22:40:13 -0800455 mService.mContext.getResources(), displayWidth, displayHeight,
Jorim Jaggi737af722015-12-31 10:42:27 +0100456 dividerSize, orientation == Configuration.ORIENTATION_PORTRAIT, outBounds);
457 final SnapTarget target = algorithm.calculateNonDismissingSnapTarget(dividerPosition);
458
459 // Recalculate the bounds based on the position of the target.
460 DockedDividerUtils.calculateBoundsForPosition(target.position, dockSide,
461 outBounds, displayInfo.logicalWidth, displayInfo.logicalHeight,
462 dividerSize);
463 }
464
Craig Mautner1bf2b872014-02-05 15:37:40 -0800465 boolean isAnimating() {
466 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
467 final ArrayList<AppWindowToken> activities = mTasks.get(taskNdx).mAppTokens;
468 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
469 final ArrayList<WindowState> windows = activities.get(activityNdx).allAppWindows;
470 for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700471 final WindowStateAnimator winAnimator = windows.get(winNdx).mWinAnimator;
Wale Ogunwalec48a3542016-02-19 15:18:45 -0800472 if (winAnimator.isAnimating() || winAnimator.mWin.mAnimatingExit) {
Craig Mautner1bf2b872014-02-05 15:37:40 -0800473 return true;
474 }
475 }
476 }
477 }
478 return false;
479 }
480
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700481 void addTask(Task task, boolean toTop) {
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700482 addTask(task, toTop, task.showForAllUsers());
Wale Ogunwale3fcb4a82015-04-06 14:00:13 -0700483 }
484
Craig Mautner00af9fe2013-03-25 09:13:41 -0700485 /**
486 * Put a Task in this stack. Used for adding and moving.
487 * @param task The task to add.
488 * @param toTop Whether to add it to the top or bottom.
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700489 * @param showForAllUsers Whether to show the task regardless of the current user.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700490 */
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700491 void addTask(Task task, boolean toTop, boolean showForAllUsers) {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700492 positionTask(task, toTop ? mTasks.size() : 0, showForAllUsers);
493 }
494
495 void positionTask(Task task, int position, boolean showForAllUsers) {
496 final boolean canShowTask =
497 showForAllUsers || mService.isCurrentProfileLocked(task.mUserId);
498 mTasks.remove(task);
499 int stackSize = mTasks.size();
500 int minPosition = 0;
501 int maxPosition = stackSize;
502
503 if (canShowTask) {
504 minPosition = computeMinPosition(minPosition, stackSize);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700505 } else {
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700506 maxPosition = computeMaxPosition(maxPosition);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700507 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700508 // Reset position based on minimum/maximum possible positions.
509 position = Math.min(Math.max(position, minPosition), maxPosition);
510
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800511 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM,
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700512 "positionTask: task=" + task + " position=" + position);
513 mTasks.add(position, task);
Craig Mautnerac6f8432013-07-17 13:24:59 -0700514
Chong Zhangf66db432016-01-13 10:39:51 -0800515 // If we are moving the task across stacks, the scroll is no longer valid.
516 if (task.mStack != this) {
517 task.resetScrollLocked();
518 }
Craig Mautner967212c2013-04-13 21:10:58 -0700519 task.mStack = this;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700520 task.updateDisplayInfo(mDisplayContent);
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700521 boolean toTop = position == mTasks.size() - 1;
raysb.kim00a27252014-11-11 08:38:21 +0900522 if (toTop) {
523 mDisplayContent.moveStack(this, true);
524 }
Wale Ogunwaleddc1cb22015-07-25 19:23:04 -0700525 EventLog.writeEvent(EventLogTags.WM_TASK_MOVED, task.mTaskId, toTop ? 1 : 0, position);
526 }
527
528 /** Calculate the minimum possible position for a task that can be shown to the user.
529 * The minimum position will be above all other tasks that can't be shown.
530 * @param minPosition The minimum position the caller is suggesting.
531 * We will start adjusting up from here.
532 * @param size The size of the current task list.
533 */
534 private int computeMinPosition(int minPosition, int size) {
535 while (minPosition < size) {
536 final Task tmpTask = mTasks.get(minPosition);
537 final boolean canShowTmpTask =
538 tmpTask.showForAllUsers()
539 || mService.isCurrentProfileLocked(tmpTask.mUserId);
540 if (canShowTmpTask) {
541 break;
542 }
543 minPosition++;
544 }
545 return minPosition;
546 }
547
548 /** Calculate the maximum possible position for a task that can't be shown to the user.
549 * The maximum position will be below all other tasks that can be shown.
550 * @param maxPosition The maximum position the caller is suggesting.
551 * We will start adjusting down from here.
552 */
553 private int computeMaxPosition(int maxPosition) {
554 while (maxPosition > 0) {
555 final Task tmpTask = mTasks.get(maxPosition - 1);
556 final boolean canShowTmpTask =
557 tmpTask.showForAllUsers()
558 || mService.isCurrentProfileLocked(tmpTask.mUserId);
559 if (!canShowTmpTask) {
560 break;
561 }
562 maxPosition--;
563 }
564 return maxPosition;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800565 }
566
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800567 void moveTaskToTop(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800568 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToTop: task=" + task + " Callers="
Craig Mautnerf0ac5c82013-06-24 11:21:57 -0700569 + Debug.getCallers(6));
Craig Mautnerd9a22882013-03-16 15:00:36 -0700570 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800571 addTask(task, true);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700572 }
573
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800574 void moveTaskToBottom(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800575 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "moveTaskToBottom: task=" + task);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700576 mTasks.remove(task);
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800577 addTask(task, false);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700578 }
579
Craig Mautner00af9fe2013-03-25 09:13:41 -0700580 /**
Craig Mautner04a0ea62014-01-13 12:51:26 -0800581 * Delete a Task from this stack. If it is the last Task in the stack, move this stack to the
582 * back.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700583 * @param task The Task to delete.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700584 */
Craig Mautnerde4ef022013-04-07 19:01:33 -0700585 void removeTask(Task task) {
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800586 if (DEBUG_TASK_MOVEMENT) Slog.d(TAG_WM, "removeTask: task=" + task);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700587 mTasks.remove(task);
Craig Mautnerdf88d732014-01-27 09:21:32 -0800588 if (mDisplayContent != null) {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800589 if (mTasks.isEmpty()) {
590 mDisplayContent.moveStack(this, false);
591 }
592 mDisplayContent.layoutNeeded = true;
Craig Mautner04a0ea62014-01-13 12:51:26 -0800593 }
Craig Mautnere3119b72015-01-20 15:02:36 -0800594 for (int appNdx = mExitingAppTokens.size() - 1; appNdx >= 0; --appNdx) {
595 final AppWindowToken wtoken = mExitingAppTokens.get(appNdx);
Craig Mautner83162a92015-01-26 14:43:30 -0800596 if (wtoken.mTask == task) {
Craig Mautnere3119b72015-01-20 15:02:36 -0800597 wtoken.mIsExiting = false;
598 mExitingAppTokens.remove(appNdx);
599 }
600 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800601 }
602
Craig Mautnerdf88d732014-01-27 09:21:32 -0800603 void attachDisplayContent(DisplayContent displayContent) {
604 if (mDisplayContent != null) {
605 throw new IllegalStateException("attachDisplayContent: Already attached");
Craig Mautner4a1cb222013-12-04 16:14:06 -0800606 }
Craig Mautnerdf88d732014-01-27 09:21:32 -0800607
608 mDisplayContent = displayContent;
Jorim Jaggibc5425c2016-03-01 13:51:16 +0100609 mAnimationBackgroundSurface = new DimLayer(mService, this, mDisplayContent.getDisplayId(),
610 "animation background stackId=" + mStackId);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700611
612 Rect bounds = null;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700613 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwale3797c222015-10-27 14:21:58 -0700614 if (mStackId == DOCKED_STACK_ID
615 || (dockedStack != null && StackId.isResizeableByDockedStack(mStackId))) {
616 // The existence of a docked stack affects the size of other static stack created since
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700617 // the docked stack occupies a dedicated region on screen.
618 bounds = new Rect();
619 displayContent.getLogicalDisplayRect(mTmpRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700620 mTmpRect2.setEmpty();
621 if (dockedStack != null) {
622 dockedStack.getRawBounds(mTmpRect2);
623 }
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800624 final boolean dockedOnTopOrLeft = mService.mDockedStackCreateMode
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700625 == DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
626 getStackDockedModeBounds(mTmpRect, bounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100627 mDisplayContent.mDividerControllerLocked.getContentWidth(),
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700628 dockedOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700629 }
630
631 updateDisplayInfo(bounds);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700632 }
633
Wale Ogunwale961f4852016-02-01 20:25:54 -0800634 void getStackDockedModeBoundsLocked(Rect outBounds, boolean ignoreVisibility) {
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800635 if ((mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId))
636 || mDisplayContent == null) {
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700637 outBounds.set(mBounds);
638 return;
639 }
640
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700641 final TaskStack dockedStack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700642 if (dockedStack == null) {
643 // Not sure why you are calling this method when there is no docked stack...
644 throw new IllegalStateException(
645 "Calling getStackDockedModeBoundsLocked() when there is no docked stack.");
646 }
Wale Ogunwale961f4852016-02-01 20:25:54 -0800647 if (!ignoreVisibility && !dockedStack.isVisibleLocked()) {
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700648 // The docked stack is being dismissed, but we caught before it finished being
649 // dismissed. In that case we want to treat it as if it is not occupying any space and
650 // let others occupy the whole display.
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -0800651 mDisplayContent.getLogicalDisplayRect(outBounds);
Filip Gruszczynski54977fe2015-10-19 17:26:45 -0700652 return;
653 }
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700654
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700655 final int dockedSide = dockedStack.getDockSide();
656 if (dockedSide == DOCKED_INVALID) {
657 // Not sure how you got here...Only thing we can do is return current bounds.
Filip Gruszczynski0bd180d2015-12-07 15:43:52 -0800658 Slog.e(TAG_WM, "Failed to get valid docked side for docked stack=" + dockedStack);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700659 outBounds.set(mBounds);
660 return;
661 }
662
663 mDisplayContent.getLogicalDisplayRect(mTmpRect);
664 dockedStack.getRawBounds(mTmpRect2);
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800665 final boolean dockedOnTopOrLeft = dockedSide == DOCKED_TOP || dockedSide == DOCKED_LEFT;
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700666 getStackDockedModeBounds(mTmpRect, outBounds, mStackId, mTmpRect2,
Jorim Jaggi1fcbab62015-11-04 16:39:50 +0100667 mDisplayContent.mDividerControllerLocked.getContentWidth(), dockedOnTopOrLeft);
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700668
669 }
670
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700671 /**
Wale Ogunwaleffc11bb2015-10-10 13:05:45 -0700672 * Outputs the bounds a stack should be given the presence of a docked stack on the display.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700673 * @param displayRect The bounds of the display the docked stack is on.
674 * @param outBounds Output bounds that should be used for the stack.
675 * @param stackId Id of stack we are calculating the bounds for.
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700676 * @param dockedBounds Bounds of the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700677 * @param dockDividerWidth We need to know the width of the divider make to the output bounds
678 * close to the side of the dock.
679 * @param dockOnTopOrLeft If the docked stack is on the top or left side of the screen.
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700680 */
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800681 private void getStackDockedModeBounds(
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700682 Rect displayRect, Rect outBounds, int stackId, Rect dockedBounds, int dockDividerWidth,
683 boolean dockOnTopOrLeft) {
Filip Gruszczynski466f3212015-09-21 17:57:57 -0700684 final boolean dockedStack = stackId == DOCKED_STACK_ID;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700685 final boolean splitHorizontally = displayRect.width() > displayRect.height();
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700686
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700687 outBounds.set(displayRect);
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700688 if (dockedStack) {
Jorim Jaggi9ea2f7b2015-11-23 18:08:28 -0800689 if (mService.mDockedStackCreateBounds != null) {
690 outBounds.set(mService.mDockedStackCreateBounds);
691 return;
692 }
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100693
694 // The initial bounds of the docked stack when it is created about half the screen space
695 // and its bounds can be adjusted after that. The bounds of all other stacks are
696 // adjusted to occupy whatever screen space the docked stack isn't occupying.
697 final DisplayInfo di = mDisplayContent.getDisplayInfo();
698 mService.mPolicy.getStableInsetsLw(di.rotation, di.logicalWidth, di.logicalHeight,
699 mTmpRect2);
700 final int position = new DividerSnapAlgorithm(mService.mContext.getResources(),
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100701 di.logicalWidth,
702 di.logicalHeight,
703 dockDividerWidth,
704 mService.mCurConfiguration.orientation == ORIENTATION_PORTRAIT,
705 mTmpRect2).getMiddleTarget().position;
706
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700707 if (dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700708 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100709 outBounds.right = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700710 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100711 outBounds.bottom = position;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700712 }
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700713 } else {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700714 if (splitHorizontally) {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100715 outBounds.left = position - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700716 } else {
Jorim Jaggid434dcb2016-01-06 17:18:44 +0100717 outBounds.top = position - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700718 }
719 }
720 return;
721 }
722
723 // Other stacks occupy whatever space is left by the docked stack.
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700724 if (!dockOnTopOrLeft) {
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700725 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700726 outBounds.right = dockedBounds.left - dockDividerWidth;
Wale Ogunwalee45899a2015-10-01 11:30:34 -0700727 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700728 outBounds.bottom = dockedBounds.top - dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700729 }
730 } else {
731 if (splitHorizontally) {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700732 outBounds.left = dockedBounds.right + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700733 } else {
Filip Gruszczynskiba47f812015-10-28 16:11:55 -0700734 outBounds.top = dockedBounds.bottom + dockDividerWidth;
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700735 }
736 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800737 DockedDividerUtils.sanitizeStackBounds(outBounds, !dockOnTopOrLeft);
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -0700738 }
739
Wale Ogunwalea9f9b372016-02-04 18:04:39 -0800740 void resetDockedStackToMiddle() {
741 if (mStackId != DOCKED_STACK_ID) {
742 throw new IllegalStateException("Not a docked stack=" + this);
743 }
744
745 mService.mDockedStackCreateBounds = null;
746
747 final Rect bounds = new Rect();
748 getStackDockedModeBoundsLocked(bounds, true /*ignoreVisibility*/);
749 mService.mH.obtainMessage(RESIZE_STACK, DOCKED_STACK_ID,
750 1 /*allowResizeInDockedMode*/, bounds).sendToTarget();
751 }
752
Craig Mautnerdc548482014-02-05 13:35:24 -0800753 void detachDisplay() {
Craig Mautnerdf88d732014-01-27 09:21:32 -0800754 EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700755
756 boolean doAnotherLayoutPass = false;
Craig Mautnerdc548482014-02-05 13:35:24 -0800757 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; --taskNdx) {
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700758 final AppTokenList appWindowTokens = mTasks.get(taskNdx).mAppTokens;
759 for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
760 final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
761 for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
Filip Gruszczynskid66af6a2015-08-31 08:57:24 -0700762 // We are in the middle of changing the state of displays/stacks/tasks. We need
763 // to finish that, before we let layout interfere with it.
Filip Gruszczynski49b80af2015-09-24 09:04:26 -0700764 mService.removeWindowLocked(appWindows.get(winNdx));
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700765 doAnotherLayoutPass = true;
766 }
767 }
Craig Mautnerdc548482014-02-05 13:35:24 -0800768 }
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700769 if (doAnotherLayoutPass) {
Filip Gruszczynski24966d42015-09-05 15:00:00 -0700770 mService.mWindowPlacerLocked.requestTraversal();
Craig Mautnerbc2a6df2014-06-13 15:08:48 -0700771 }
772
Craig Mautner00a66752015-03-23 14:00:47 -0700773 close();
Craig Mautner00af9fe2013-03-25 09:13:41 -0700774 }
775
Craig Mautner05d29032013-05-03 13:40:13 -0700776 void resetAnimationBackgroundAnimator() {
777 mAnimationBackgroundAnimator = null;
778 mAnimationBackgroundSurface.hide();
779 }
780
Craig Mautner05d29032013-05-03 13:40:13 -0700781 void setAnimationBackground(WindowStateAnimator winAnimator, int color) {
782 int animLayer = winAnimator.mAnimLayer;
783 if (mAnimationBackgroundAnimator == null
784 || animLayer < mAnimationBackgroundAnimator.mAnimLayer) {
785 mAnimationBackgroundAnimator = winAnimator;
786 animLayer = mService.adjustAnimationBackground(winAnimator);
787 mAnimationBackgroundSurface.show(animLayer - WindowManagerService.LAYER_OFFSET_DIM,
788 ((color >> 24) & 0xff) / 255f, 0);
789 }
790 }
791
Wale Ogunwale498e8c92015-02-13 09:42:46 -0800792 void switchUser() {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700793 int top = mTasks.size();
794 for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
795 Task task = mTasks.get(taskNdx);
Wale Ogunwale6dfdfd62015-04-15 12:01:38 -0700796 if (mService.isCurrentProfileLocked(task.mUserId) || task.showForAllUsers()) {
Craig Mautnerac6f8432013-07-17 13:24:59 -0700797 mTasks.remove(taskNdx);
798 mTasks.add(task);
799 --top;
800 }
801 }
802 }
803
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800804 void close() {
Craig Mautner00a66752015-03-23 14:00:47 -0700805 if (mAnimationBackgroundSurface != null) {
806 mAnimationBackgroundSurface.destroySurface();
807 mAnimationBackgroundSurface = null;
808 }
Filip Gruszczynski26ed2652015-08-10 11:02:53 -0700809 mDisplayContent = null;
Craig Mautnerbdc748af2013-12-02 14:08:25 -0800810 }
811
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800812 /**
813 * Adjusts the stack bounds if the IME is visible.
814 *
815 * @param imeWin The IME window.
816 */
817 void setAdjustedForIme(WindowState imeWin) {
818 mAdjustedForIme = true;
819 mImeWin = imeWin;
Chong Zhangbaba7832016-03-24 10:21:26 -0700820 mImeGoingAway = false;
821 }
822
823 boolean isAdjustedForIme() {
824 return mAdjustedForIme || mImeGoingAway;
825 }
826 void clearImeGoingAway() {
827 mImeGoingAway = false;
828 }
829
830 boolean isAnimatingForIme() {
831 return mImeWin != null && mImeWin.isAnimatingLw();
832 }
833
834 /**
835 * Update the stack's bounds (crop or position) according to the IME window's
836 * current position. When IME window is animated, the bottom stack is animated
837 * together to track the IME window's current position, and the top stack is
838 * cropped as necessary.
839 *
840 * @return true if a traversal should be performed after the adjustment.
841 */
842 boolean updateAdjustForIme() {
843 boolean stopped = false;
844 if (mImeGoingAway && (!ANIMATE_IME_GOING_AWAY || !isAnimatingForIme())) {
845 mImeWin = null;
846 mAdjustedForIme = false;
847 stopped = true;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700848 }
Chong Zhangbaba7832016-03-24 10:21:26 -0700849 // Make sure to run a traversal when the animation stops so that the stack
850 // is moved to its final position.
851 return updateAdjustedBounds() || stopped;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800852 }
853
854 /**
855 * Resets the adjustment after it got adjusted for the IME.
Chong Zhangbaba7832016-03-24 10:21:26 -0700856 * @param adjustBoundsNow if true, reset and update the bounds immediately and forget about
857 * animations; otherwise, set flag and animates the window away together
858 * with IME window.
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800859 */
Chong Zhangbaba7832016-03-24 10:21:26 -0700860 void resetAdjustedForIme(boolean adjustBoundsNow) {
861 if (adjustBoundsNow) {
862 mImeWin = null;
863 mAdjustedForIme = false;
864 mImeGoingAway = false;
865 updateAdjustedBounds();
866 } else {
867 mImeGoingAway |= mAdjustedForIme;
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700868 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800869 }
870
871 /**
872 * Sets the amount how much we currently minimize our stack.
873 *
874 * @param minimizeAmount The amount, between 0 and 1.
875 * @return Whether the amount has changed and a layout is needed.
876 */
877 boolean setAdjustedForMinimizedDock(float minimizeAmount) {
878 if (minimizeAmount != mMinimizeAmount) {
879 mMinimizeAmount = minimizeAmount;
880 updateAdjustedBounds();
881 return isVisibleForUserLocked();
882 } else {
883 return false;
884 }
885 }
886
Jorim Jaggi409635b2016-04-01 15:32:28 -0700887 boolean isAdjustedForMinimizedDock() {
888 return mMinimizeAmount != 0f;
889 }
890
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800891 private boolean adjustForIME(final WindowState imeWin) {
892 final int dockedSide = getDockSide();
893 final boolean dockedTopOrBottom = dockedSide == DOCKED_TOP || dockedSide == DOCKED_BOTTOM;
894 final Rect adjustedBounds = mTmpAdjustedBounds;
895 if (imeWin == null || !dockedTopOrBottom) {
896 return false;
897 }
898
899 final Rect displayContentRect = mTmpRect;
900 final Rect contentBounds = mTmpRect2;
901
902 // Calculate the content bounds excluding the area occupied by IME
903 getDisplayContent().getContentRect(displayContentRect);
904 contentBounds.set(displayContentRect);
905 int imeTop = Math.max(imeWin.getDisplayFrameLw().top, contentBounds.top);
Chong Zhangbaba7832016-03-24 10:21:26 -0700906
907 // if IME window is animating, get its actual vertical shown position (but no smaller than
908 // the final target vertical position)
909 if (imeWin.isAnimatingLw()) {
910 imeTop = Math.max(imeTop, imeWin.getShownPositionLw().y);
911 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800912 imeTop += imeWin.getGivenContentInsetsLw().top;
913 if (contentBounds.bottom > imeTop) {
914 contentBounds.bottom = imeTop;
915 }
916
917 // If content bounds not changing, nothing to do.
918 if (mLastContentBounds.equals(contentBounds)) {
919 return true;
920 }
921
922 // Content bounds changed, need to apply adjustments depending on dock sides.
923 mLastContentBounds.set(contentBounds);
924 adjustedBounds.set(mBounds);
925 final int yOffset = displayContentRect.bottom - contentBounds.bottom;
926
927 if (dockedSide == DOCKED_TOP) {
928 // If this stack is docked on top, we make it smaller so the bottom stack is not
929 // occluded by IME. We shift its bottom up by the height of the IME (capped by
930 // the display content rect). Note that we don't change the task bounds.
931 adjustedBounds.bottom = Math.max(
932 adjustedBounds.bottom - yOffset, displayContentRect.top);
933 } else {
934 // If this stack is docked on bottom, we shift it up so that it's not occluded by
935 // IME. We try to move it up by the height of the IME window (although the best
936 // we could do is to make the top stack fully collapsed).
937 final int dividerWidth = getDisplayContent().mDividerControllerLocked
938 .getContentWidth();
939 adjustedBounds.top = Math.max(
940 adjustedBounds.top - yOffset, displayContentRect.top + dividerWidth);
941 adjustedBounds.bottom = adjustedBounds.top + mBounds.height();
942 }
943 return true;
944 }
945
946 private boolean adjustForMinimizedDockedStack(float minimizeAmount) {
947 final int dockSide = getDockSide();
948 if (dockSide == DOCKED_INVALID && !mTmpAdjustedBounds.isEmpty()) {
949 return false;
950 }
951
952 if (dockSide == DOCKED_TOP) {
953 mService.getStableInsetsLocked(mTmpRect);
954 int topInset = mTmpRect.top;
955 mTmpAdjustedBounds.set(mBounds);
956 mTmpAdjustedBounds.bottom =
957 (int) (minimizeAmount * topInset + (1 - minimizeAmount) * mBounds.bottom);
958 } else if (dockSide == DOCKED_LEFT) {
959 mTmpAdjustedBounds.set(mBounds);
Jorim Jaggibcff1432016-04-01 15:49:45 -0700960 final int width = mBounds.width();
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800961 mTmpAdjustedBounds.right =
962 (int) (minimizeAmount * mDockedStackMinimizeThickness
963 + (1 - minimizeAmount) * mBounds.right);
Jorim Jaggibcff1432016-04-01 15:49:45 -0700964 mTmpAdjustedBounds.left = mTmpAdjustedBounds.right - width;
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800965 } else if (dockSide == DOCKED_RIGHT) {
966 mTmpAdjustedBounds.set(mBounds);
967 mTmpAdjustedBounds.left =
968 (int) (minimizeAmount * (mBounds.right - mDockedStackMinimizeThickness)
969 + (1 - minimizeAmount) * mBounds.left);
970 }
971 return true;
972 }
973
974 /**
Jorim Jaggif97ed922016-02-18 18:57:07 -0800975 * @return the distance in pixels how much the stack gets minimized from it's original size
976 */
977 int getMinimizeDistance() {
978 final int dockSide = getDockSide();
979 if (dockSide == DOCKED_INVALID) {
980 return 0;
981 }
982
983 if (dockSide == DOCKED_TOP) {
984 mService.getStableInsetsLocked(mTmpRect);
985 int topInset = mTmpRect.top;
986 return mBounds.bottom - topInset;
987 } else if (dockSide == DOCKED_LEFT || dockSide == DOCKED_RIGHT) {
988 return mBounds.width() - mDockedStackMinimizeThickness;
989 } else {
990 return 0;
991 }
992 }
993
994 /**
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800995 * Updates the adjustment depending on it's current state.
996 */
Chong Zhangb58bbcc2016-03-23 11:57:36 -0700997 boolean updateAdjustedBounds() {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -0800998 boolean adjust = false;
999 if (mMinimizeAmount != 0f) {
1000 adjust = adjustForMinimizedDockedStack(mMinimizeAmount);
1001 } else if (mAdjustedForIme) {
1002 adjust = adjustForIME(mImeWin);
1003 }
1004 if (!adjust) {
1005 mTmpAdjustedBounds.setEmpty();
1006 mLastContentBounds.setEmpty();
1007 }
Chong Zhangb58bbcc2016-03-23 11:57:36 -07001008 return setAdjustedBounds(mTmpAdjustedBounds, isAdjustedForMinimizedDockedStack());
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001009 }
1010
1011 boolean isAdjustedForMinimizedDockedStack() {
1012 return mMinimizeAmount != 0f;
1013 }
1014
Craig Mautner00af9fe2013-03-25 09:13:41 -07001015 public void dump(String prefix, PrintWriter pw) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001016 pw.println(prefix + "mStackId=" + mStackId);
1017 pw.println(prefix + "mDeferDetach=" + mDeferDetach);
1018 pw.println(prefix + "mFullscreen=" + mFullscreen);
1019 pw.println(prefix + "mBounds=" + mBounds.toShortString());
1020 for (int taskNdx = mTasks.size() - 1; taskNdx >= 0; taskNdx--) {
1021 mTasks.get(taskNdx).dump(prefix + " ", pw);
Craig Mautner00af9fe2013-03-25 09:13:41 -07001022 }
Craig Mautner05d29032013-05-03 13:40:13 -07001023 if (mAnimationBackgroundSurface.isDimming()) {
Wale Ogunwaleb429e682016-01-06 12:36:34 -08001024 pw.println(prefix + "mWindowAnimationBackgroundSurface:");
Craig Mautner05d29032013-05-03 13:40:13 -07001025 mAnimationBackgroundSurface.printTo(prefix + " ", pw);
1026 }
Craig Mautnerdc548482014-02-05 13:35:24 -08001027 if (!mExitingAppTokens.isEmpty()) {
1028 pw.println();
1029 pw.println(" Exiting application tokens:");
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001030 for (int i = mExitingAppTokens.size() - 1; i >= 0; i--) {
Craig Mautnerdc548482014-02-05 13:35:24 -08001031 WindowToken token = mExitingAppTokens.get(i);
1032 pw.print(" Exiting App #"); pw.print(i);
1033 pw.print(' '); pw.print(token);
1034 pw.println(':');
1035 token.dump(pw, " ");
1036 }
1037 }
Craig Mautner00af9fe2013-03-25 09:13:41 -07001038 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001039
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001040 /** Fullscreen status of the stack without adjusting for other factors in the system like
1041 * visibility of docked stack.
1042 * Most callers should be using {@link #isFullscreen} as it take into consideration other
1043 * system factors. */
1044 boolean getRawFullscreen() {
1045 return mFullscreen;
1046 }
1047
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001048 @Override
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001049 public boolean isFullscreen() {
Wale Ogunwalef175e8a2015-09-29 11:07:06 -07001050 if (useCurrentBounds()) {
1051 return mFullscreen;
1052 }
1053 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack
1054 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the
1055 // system.
1056 return true;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001057 }
1058
1059 @Override
1060 public DisplayInfo getDisplayInfo() {
1061 return mDisplayContent.getDisplayInfo();
1062 }
1063
1064 @Override
Craig Mautner4cd0c13f2013-04-16 15:55:52 -07001065 public String toString() {
1066 return "{stackId=" + mStackId + " tasks=" + mTasks + "}";
1067 }
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001068
Filip Gruszczynski0689ae92015-10-01 12:30:31 -07001069 @Override
1070 public String toShortString() {
1071 return "Stack=" + mStackId;
1072 }
1073
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001074 /**
Chong Zhangc806d902015-11-30 09:44:27 -08001075 * For docked workspace (or workspace that's side-by-side to the docked), provides
1076 * information which side of the screen was the dock anchored.
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001077 */
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001078 int getDockSide() {
Jorim Jaggi737af722015-12-31 10:42:27 +01001079 return getDockSide(mBounds);
1080 }
1081
1082 int getDockSide(Rect bounds) {
Chong Zhangc806d902015-11-30 09:44:27 -08001083 if (mStackId != DOCKED_STACK_ID && !StackId.isResizeableByDockedStack(mStackId)) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001084 return DOCKED_INVALID;
1085 }
1086 if (mDisplayContent == null) {
1087 return DOCKED_INVALID;
1088 }
1089 mDisplayContent.getLogicalDisplayRect(mTmpRect);
1090 final int orientation = mService.mCurConfiguration.orientation;
1091 if (orientation == Configuration.ORIENTATION_PORTRAIT) {
1092 // Portrait mode, docked either at the top or the bottom.
Jorim Jaggi067e8172016-02-03 18:24:12 -08001093 if (bounds.top - mTmpRect.top <= mTmpRect.bottom - bounds.bottom) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001094 return DOCKED_TOP;
1095 } else {
1096 return DOCKED_BOTTOM;
1097 }
1098 } else if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
1099 // Landscape mode, docked either on the left or on the right.
Jorim Jaggi067e8172016-02-03 18:24:12 -08001100 if (bounds.left - mTmpRect.left <= mTmpRect.right - bounds.right) {
Filip Gruszczynski923f8262015-09-17 17:41:13 -07001101 return DOCKED_LEFT;
1102 } else {
1103 return DOCKED_RIGHT;
1104 }
1105 } else {
1106 return DOCKED_INVALID;
1107 }
1108 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001109
1110 boolean isVisibleLocked() {
Jorim Jaggi7998e482016-02-12 18:47:06 -08001111 final boolean keyguardOn = mService.mPolicy.isKeyguardShowingOrOccluded()
1112 && !mService.mAnimator.mKeyguardGoingAway;
Chong Zhang75b37202015-12-04 14:16:36 -08001113 if (keyguardOn && !StackId.isAllowedOverLockscreen(mStackId)) {
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -08001114 // The keyguard is showing and the stack shouldn't show on top of the keyguard.
Wale Ogunwale961f4852016-02-01 20:25:54 -08001115 return false;
Chong Zhang75b37202015-12-04 14:16:36 -08001116 }
Wale Ogunwaleccb6ce22016-01-14 15:36:35 -08001117
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001118 for (int i = mTasks.size() - 1; i >= 0; i--) {
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001119 final Task task = mTasks.get(i);
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001120 for (int j = task.mAppTokens.size() - 1; j >= 0; j--) {
1121 if (!task.mAppTokens.get(j).hidden) {
1122 return true;
1123 }
1124 }
1125 }
Jorim Jaggi42625d1b2016-02-11 20:11:07 -08001126
1127 return false;
1128 }
1129
1130 /**
1131 * @return true if a the stack is visible for the current in user, ignoring any other visibility
1132 * aspects, and false otherwise
1133 */
1134 boolean isVisibleForUserLocked() {
1135 for (int i = mTasks.size() - 1; i >= 0; i--) {
1136 final Task task = mTasks.get(i);
1137 if (task.isVisibleForUser()) {
1138 return true;
1139 }
1140 }
Filip Gruszczynski3ddc5d62015-09-23 15:01:30 -07001141 return false;
1142 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001143
Wale Ogunwalece144522016-02-05 22:51:01 -08001144 boolean isDragResizing() {
1145 return mDragResizing;
1146 }
1147
Jorim Jaggic662d8e2016-02-05 16:54:54 -08001148 private void setDragResizingLocked(boolean resizing) {
1149 if (mDragResizing == resizing) {
1150 return;
1151 }
1152 mDragResizing = resizing;
1153 for (int i = mTasks.size() - 1; i >= 0 ; i--) {
1154 mTasks.get(i).resetDragResizingChangeReported();
1155 }
1156 }
1157
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001158 @Override // AnimatesBounds
1159 public boolean setSize(Rect bounds) {
1160 synchronized (mService.mWindowMap) {
1161 if (mDisplayContent == null) {
1162 return false;
1163 }
1164 }
1165 try {
Wale Ogunwalee75a9ad2016-03-18 20:43:49 -07001166 mService.mActivityManager.resizeStack(mStackId, bounds, false, true, false, -1);
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001167 } catch (RemoteException e) {
1168 }
1169 return true;
1170 }
1171
Robert Carr0d00c2e2016-02-29 17:45:02 -08001172 public boolean setPinnedStackSize(Rect bounds, Rect tempTaskBounds) {
1173 synchronized (mService.mWindowMap) {
1174 if (mDisplayContent == null) {
1175 return false;
1176 }
1177 if (mStackId != PINNED_STACK_ID) {
1178 Slog.w(TAG_WM, "Attempt to use pinned stack resize animation helper on"
1179 + "non pinned stack");
1180 return false;
1181 }
1182 }
1183 try {
1184 mService.mActivityManager.resizePinnedStack(bounds, tempTaskBounds);
1185 } catch (RemoteException e) {
1186 // I don't believe you.
1187 }
1188 return true;
1189 }
1190
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001191 @Override // AnimatesBounds
Wale Ogunwalece144522016-02-05 22:51:01 -08001192 public void onAnimationStart() {
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001193 synchronized (mService.mWindowMap) {
Robert Carr0d00c2e2016-02-29 17:45:02 -08001194 mFreezeMovementAnimations = true;
1195 mForceScaleToCrop = true;
Wale Ogunwalece144522016-02-05 22:51:01 -08001196 }
1197 }
1198
1199 @Override // AnimatesBounds
1200 public void onAnimationEnd() {
1201 synchronized (mService.mWindowMap) {
Robert Carr0d00c2e2016-02-29 17:45:02 -08001202 mFreezeMovementAnimations = false;
1203 mForceScaleToCrop = false;
Wale Ogunwalece144522016-02-05 22:51:01 -08001204 mService.requestTraversal();
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001205 }
Wale Ogunwale480dca02016-02-06 13:58:29 -08001206 if (mStackId == PINNED_STACK_ID) {
1207 try {
1208 mService.mActivityManager.notifyPinnedStackAnimationEnded();
1209 } catch (RemoteException e) {
1210 // I don't believe you...
1211 }
1212 }
Filip Gruszczynski84fa3352016-01-25 16:28:49 -08001213 }
Filip Gruszczynskic17d8b72016-02-03 16:52:59 -08001214
1215 @Override
1216 public void moveToFullscreen() {
1217 try {
1218 mService.mActivityManager.moveTasksToFullscreenStack(mStackId, true);
1219 } catch (RemoteException e) {
1220 e.printStackTrace();
1221 }
1222 }
1223
1224 @Override
1225 public void getFullScreenBounds(Rect bounds) {
1226 getDisplayContent().getContentRect(bounds);
1227 }
Robert Carr0d00c2e2016-02-29 17:45:02 -08001228
1229 public boolean getFreezeMovementAnimations() {
1230 return mFreezeMovementAnimations;
1231 }
1232
1233 public boolean getForceScaleToCrop() {
1234 return mForceScaleToCrop;
1235 }
Wale Ogunwaleecbcadd2016-02-21 14:18:51 -08001236}