blob: 45f018ddd287fa464ea9b7e6a19b8e1c1c95b7c0 [file] [log] [blame]
Craig Mautner59c00972012-07-30 12:10:24 -07001/*
2 * Copyright (C) 2012 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
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070019import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
Craig Mautnerde4ef022013-04-07 19:01:33 -070020import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
Craig Mautner858d8a62013-04-23 17:08:34 -070021import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
Craig Mautnerde4ef022013-04-07 19:01:33 -070022import static com.android.server.wm.WindowManagerService.TAG;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070023
Craig Mautnerc00204b2013-03-05 15:02:14 -080024import android.graphics.Rect;
Craig Mautnerde4ef022013-04-07 19:01:33 -070025import android.util.Slog;
Craig Mautner858d8a62013-04-23 17:08:34 -070026import android.util.SparseArray;
Craig Mautnerb47bbc32012-08-22 17:41:48 -070027import android.view.Display;
Craig Mautner59c00972012-07-30 12:10:24 -070028import android.view.DisplayInfo;
Craig Mautnercf910b02013-04-23 11:23:27 -070029import android.view.InputChannel;
Craig Mautner59c00972012-07-30 12:10:24 -070030
31import java.io.PrintWriter;
32import java.util.ArrayList;
33
34class DisplayContentList extends ArrayList<DisplayContent> {
35}
36
37/**
38 * Utility class for keeping track of the WindowStates and other pertinent contents of a
39 * particular Display.
40 *
41 * IMPORTANT: No method from this class should ever be used without holding
42 * WindowManagerService.mWindowMap.
43 */
44class DisplayContent {
45
46 /** Unique identifier of this stack. */
47 private final int mDisplayId;
48
49 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
50 * from mDisplayWindows; */
51 private WindowList mWindows = new WindowList();
52
Craig Mautner59c00972012-07-30 12:10:24 -070053 // This protects the following display size properties, so that
54 // getDisplaySize() doesn't need to acquire the global lock. This is
55 // needed because the window manager sometimes needs to use ActivityThread
56 // while it has its global state locked (for example to load animation
57 // resources), but the ActivityThread also needs get the current display
58 // size sometimes when it has its package lock held.
59 //
60 // These will only be modified with both mWindowMap and mDisplaySizeLock
61 // held (in that order) so the window manager doesn't need to acquire this
62 // lock when needing these values in its normal operation.
63 final Object mDisplaySizeLock = new Object();
64 int mInitialDisplayWidth = 0;
65 int mInitialDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -070066 int mInitialDisplayDensity = 0;
Craig Mautner59c00972012-07-30 12:10:24 -070067 int mBaseDisplayWidth = 0;
68 int mBaseDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -070069 int mBaseDisplayDensity = 0;
Craig Mautner2d5618c2012-10-18 13:55:47 -070070 private final DisplayInfo mDisplayInfo = new DisplayInfo();
71 private final Display mDisplay;
Craig Mautner59c00972012-07-30 12:10:24 -070072
Craig Mautner39834192012-09-02 07:47:24 -070073 // Accessed directly by all users.
74 boolean layoutNeeded;
Craig Mautner76a71652012-09-03 23:23:58 -070075 int pendingLayoutChanges;
Craig Mautner69b08182012-09-05 13:07:13 -070076 final boolean isDefaultDisplay;
Craig Mautner39834192012-09-02 07:47:24 -070077
Craig Mautner2d5618c2012-10-18 13:55:47 -070078 /**
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080079 * Window tokens that are in the process of exiting, but still
80 * on screen for animations.
81 */
82 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
83
84 /**
85 * Application tokens that are in the process of exiting, but still
86 * on screen for animations.
87 */
88 final AppTokenList mExitingAppTokens = new AppTokenList();
89
Craig Mautnercf910b02013-04-23 11:23:27 -070090 /** Array containing the home StackBox and possibly one more which would contain apps. Array
91 * is stored in display order with the current bottom stack at 0. */
Craig Mautner00af9fe2013-03-25 09:13:41 -070092 private ArrayList<StackBox> mStackBoxes = new ArrayList<StackBox>();
Craig Mautnerc00204b2013-03-05 15:02:14 -080093
Craig Mautnercf910b02013-04-23 11:23:27 -070094 /** True when the home StackBox is at the top of mStackBoxes, false otherwise. */
Craig Mautnerde4ef022013-04-07 19:01:33 -070095 private TaskStack mHomeStack = null;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070096
Craig Mautner4cd0c13f2013-04-16 15:55:52 -070097 /** Save allocating when retrieving tasks */
Craig Mautnerd9a22882013-03-16 15:00:36 -070098 ArrayList<Task> mTmpTasks = new ArrayList<Task>();
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080099
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700100 /** Sorted most recent at top, oldest at [0]. */
101 ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>();
102
Craig Mautnercf910b02013-04-23 11:23:27 -0700103 /** Forward motion events to mTapDetector. */
104 InputChannel mTapInputChannel;
105
106 /** Detect user tapping outside of current focused stack bounds .*/
107 StackTapDetector mTapDetector;
108
Craig Mautner858d8a62013-04-23 17:08:34 -0700109 SparseArray<UserStacks> mUserStacks = new SparseArray<UserStacks>();
110
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800111 /**
Craig Mautner2d5618c2012-10-18 13:55:47 -0700112 * @param display May not be null.
113 */
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700114 DisplayContent(Display display) {
115 mDisplay = display;
116 mDisplayId = display.getDisplayId();
117 display.getDisplayInfo(mDisplayInfo);
Craig Mautner69b08182012-09-05 13:07:13 -0700118 isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
Craig Mautner59c00972012-07-30 12:10:24 -0700119 }
120
121 int getDisplayId() {
122 return mDisplayId;
123 }
124
125 WindowList getWindowList() {
126 return mWindows;
127 }
128
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700129 Display getDisplay() {
130 return mDisplay;
131 }
132
Craig Mautner59c00972012-07-30 12:10:24 -0700133 DisplayInfo getDisplayInfo() {
134 return mDisplayInfo;
135 }
136
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700137 boolean homeOnTop() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700138 return mStackBoxes.get(0).mStack != mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700139 }
140
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700141 void moveStack(TaskStack stack, boolean toTop) {
142 mStackHistory.remove(stack);
143 mStackHistory.add(toTop ? mStackHistory.size() : 0, stack);
144 }
145
Craig Mautner00af9fe2013-03-25 09:13:41 -0700146 /**
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700147 * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700148 * @return All the Tasks, in order, on this display.
149 */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800150 ArrayList<Task> getTasks() {
Craig Mautnerd9a22882013-03-16 15:00:36 -0700151 mTmpTasks.clear();
Craig Mautner858d8a62013-04-23 17:08:34 -0700152 // First do the tasks belonging to other users.
153 final int numUserStacks = mUserStacks.size();
154 for (int i = 0; i < numUserStacks; ++i) {
155 UserStacks userStacks = mUserStacks.valueAt(i);
156 ArrayList<TaskStack> stacks = userStacks.mSavedStackHistory;
157 final int numStacks = stacks.size();
158 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
159 TaskStack stack = stacks.get(stackNdx);
160 if (stack != mHomeStack) {
161 if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" +
162 mStackHistory);
163 mTmpTasks.addAll(stack.getTasks());
164 }
165 }
166 }
167 // Now do the current user's tasks.
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700168 final int numStacks = mStackHistory.size();
169 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
170 mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
Craig Mautnerd9a22882013-03-16 15:00:36 -0700171 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700172 if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" +
173 mStackHistory);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700174 return mTmpTasks;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800175 }
176
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700177 TaskStack getHomeStack() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700178 return mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700179 }
180
Craig Mautner722285e2012-09-07 13:55:58 -0700181 public void updateDisplayInfo() {
182 mDisplay.getDisplayInfo(mDisplayInfo);
183 }
184
Craig Mautner00af9fe2013-03-25 09:13:41 -0700185 /** @return The number of tokens in all of the Tasks on this display. */
Craig Mautnerf81b90872013-02-26 13:02:43 -0800186 int numTokens() {
Craig Mautnerd9a22882013-03-16 15:00:36 -0700187 getTasks();
Craig Mautnerf81b90872013-02-26 13:02:43 -0800188 int count = 0;
Craig Mautnerd9a22882013-03-16 15:00:36 -0700189 for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
190 count += mTmpTasks.get(taskNdx).mAppTokens.size();
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800191 }
Craig Mautnerf81b90872013-02-26 13:02:43 -0800192 return count;
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800193 }
194
Craig Mautner00af9fe2013-03-25 09:13:41 -0700195 /** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800196 TaskStack createStack(int stackId, int relativeStackId, int position, float weight) {
197 TaskStack newStack = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700198 if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackId="
199 + relativeStackId + " position=" + position + " weight=" + weight);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800200 if (mStackBoxes.isEmpty()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700201 if (stackId != HOME_STACK_ID) {
202 throw new IllegalArgumentException("createStack: First stackId not "
203 + HOME_STACK_ID);
204 }
Craig Mautner967212c2013-04-13 21:10:58 -0700205 StackBox newBox = new StackBox(this, null);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800206 mStackBoxes.add(newBox);
Craig Mautner967212c2013-04-13 21:10:58 -0700207 newStack = new TaskStack(stackId, this);
208 newStack.mStackBox = newBox;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800209 newBox.mStack = newStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700210 mHomeStack = newStack;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800211 } else {
212 int stackBoxNdx;
213 for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
214 final StackBox box = mStackBoxes.get(stackBoxNdx);
215 if (position == StackBox.TASK_STACK_GOES_OVER
216 || position == StackBox.TASK_STACK_GOES_UNDER) {
217 // Position indicates a new box is added at top level only.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700218 if (box.contains(relativeStackId)) {
Craig Mautner967212c2013-04-13 21:10:58 -0700219 StackBox newBox = new StackBox(this, null);
220 newStack = new TaskStack(stackId, this);
221 newStack.mStackBox = newBox;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800222 newBox.mStack = newStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700223 final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
224 if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +
225 (stackBoxNdx + offset));
Craig Mautnerc00204b2013-03-05 15:02:14 -0800226 mStackBoxes.add(stackBoxNdx + offset, newBox);
227 break;
228 }
229 } else {
230 // Remaining position values indicate a box must be split.
231 newStack = box.split(stackId, relativeStackId, position, weight);
232 if (newStack != null) {
233 break;
234 }
235 }
236 }
Craig Mautner00af9fe2013-03-25 09:13:41 -0700237 if (stackBoxNdx < 0) {
238 throw new IllegalArgumentException("createStack: stackId " + relativeStackId
239 + " not found.");
Craig Mautnerc00204b2013-03-05 15:02:14 -0800240 }
241 }
Craig Mautner967212c2013-04-13 21:10:58 -0700242 if (newStack != null) {
243 layoutNeeded = true;
244 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800245 return newStack;
246 }
247
Craig Mautner00af9fe2013-03-25 09:13:41 -0700248 /** Refer to {@link WindowManagerService#resizeStack(int, float)} */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800249 boolean resizeStack(int stackId, float weight) {
Craig Mautner967212c2013-04-13 21:10:58 -0700250 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
Craig Mautnerc00204b2013-03-05 15:02:14 -0800251 final StackBox box = mStackBoxes.get(stackBoxNdx);
252 if (box.resize(stackId, weight)) {
253 return true;
254 }
255 }
256 return false;
257 }
258
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700259 void addStackBox(StackBox box, boolean toTop) {
260 if (mStackBoxes.size() >= 2) {
261 throw new RuntimeException("addStackBox: Too many toplevel StackBoxes!");
262 }
263 mStackBoxes.add(toTop ? mStackBoxes.size() : 0, box);
264 }
265
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700266 void removeStackBox(StackBox box) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700267 if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700268 final TaskStack stack = box.mStack;
269 if (stack != null && stack.mStackId == HOME_STACK_ID) {
270 // Never delete the home stack, even if it is empty.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700271 if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack.");
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700272 return;
273 }
274 mStackBoxes.remove(box);
275 }
276
Craig Mautner00af9fe2013-03-25 09:13:41 -0700277 /**
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700278 * Move the home StackBox to the top or bottom of mStackBoxes. That is the only place
279 * it is allowed to be. This is a nop if the home StackBox is already in the correct position.
280 * @param toTop Move home to the top of mStackBoxes if true, to the bottom if false.
281 * @return true if a change was made, false otherwise.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700282 */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700283 boolean moveHomeStackBox(boolean toTop) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700284 if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop);
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700285 switch (mStackBoxes.size()) {
286 case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
287 case 1: return false; // Only the home StackBox exists.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700288 case 2:
289 if (homeOnTop() ^ toTop) {
290 mStackBoxes.add(mStackBoxes.remove(0));
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700291 return true;
292 }
293 return false;
294 default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!");
Craig Mautner00af9fe2013-03-25 09:13:41 -0700295 }
296 }
297
Craig Mautner967212c2013-04-13 21:10:58 -0700298 /**
299 * Propagate the new bounds to all child stack boxes, applying weights as we move down.
300 * @param contentRect The bounds to apply at the top level.
301 */
302 void setStackBoxSize(Rect contentRect) {
303 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
304 mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect);
305 }
306 }
307
308 Rect getStackBounds(int stackId) {
309 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
310 Rect bounds = mStackBoxes.get(stackBoxNdx).getStackBounds(stackId);
311 if (bounds != null) {
312 return bounds;
313 }
314 }
Craig Mautner858d8a62013-04-23 17:08:34 -0700315 // Not in the visible stacks, try the saved ones.
316 for (int userNdx = mUserStacks.size() - 1; userNdx >= 0; --userNdx) {
317 UserStacks userStacks = mUserStacks.valueAt(userNdx);
318 Rect bounds = userStacks.mSavedStackBox.getStackBounds(stackId);
319 if (bounds != null) {
320 return bounds;
321 }
322 }
Craig Mautner967212c2013-04-13 21:10:58 -0700323 return null;
324 }
325
Craig Mautnercf910b02013-04-23 11:23:27 -0700326 int stackIdFromPoint(int x, int y) {
327 StackBox topBox = mStackBoxes.get(mStackBoxes.size() - 1);
328 return topBox.stackIdFromPoint(x, y);
329 }
330
Craig Mautner858d8a62013-04-23 17:08:34 -0700331 void switchUserStacks(int oldUserId, int newUserId) {
332 final WindowList windows = getWindowList();
333 for (int i = 0; i < windows.size(); i++) {
334 final WindowState win = windows.get(i);
335 if (win.isHiddenFromUserLocked()) {
336 if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding "
337 + win + ", attrs=" + win.mAttrs.type + ", belonging to "
338 + win.mOwnerUid);
339 win.hideLw(false);
340 }
341 }
342 // Clear the old user's non-home StackBox
343 mUserStacks.put(oldUserId, new UserStacks());
344 UserStacks userStacks = mUserStacks.get(newUserId);
345 if (userStacks != null) {
346 userStacks.restore();
347 mUserStacks.delete(newUserId);
348 }
349 }
350
Craig Mautnera91f9e22012-09-14 16:22:08 -0700351 public void dump(String prefix, PrintWriter pw) {
352 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
353 final String subPrefix = " " + prefix;
354 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
355 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
356 pw.print("dpi");
357 if (mInitialDisplayWidth != mBaseDisplayWidth
358 || mInitialDisplayHeight != mBaseDisplayHeight
359 || mInitialDisplayDensity != mBaseDisplayDensity) {
360 pw.print(" base=");
361 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
362 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
363 }
364 pw.print(" cur=");
365 pw.print(mDisplayInfo.logicalWidth);
366 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
367 pw.print(" app=");
368 pw.print(mDisplayInfo.appWidth);
369 pw.print("x"); pw.print(mDisplayInfo.appHeight);
370 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
371 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
372 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
373 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Dianne Hackbornc652de82013-02-15 16:32:56 -0800374 pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700375 for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
376 pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
377 mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
378 }
379 int ndx = numTokens();
380 if (ndx > 0) {
381 pw.println();
382 pw.println(" Application tokens in Z order:");
383 getTasks();
384 for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
385 AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
386 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
387 final AppWindowToken wtoken = tokens.get(tokenNdx);
388 pw.print(" App #"); pw.print(ndx--);
389 pw.print(' '); pw.print(wtoken); pw.println(":");
390 wtoken.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800391 }
392 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700393 }
394 if (mExitingTokens.size() > 0) {
395 pw.println();
396 pw.println(" Exiting tokens:");
397 for (int i=mExitingTokens.size()-1; i>=0; i--) {
398 WindowToken token = mExitingTokens.get(i);
399 pw.print(" Exiting #"); pw.print(i);
400 pw.print(' '); pw.print(token);
401 pw.println(':');
402 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800403 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700404 }
405 if (mExitingAppTokens.size() > 0) {
406 pw.println();
407 pw.println(" Exiting application tokens:");
408 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
409 WindowToken token = mExitingAppTokens.get(i);
410 pw.print(" Exiting App #"); pw.print(i);
411 pw.print(' '); pw.print(token);
412 pw.println(':');
413 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800414 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700415 }
Craig Mautner858d8a62013-04-23 17:08:34 -0700416 if (mUserStacks.size() > 0) {
417 pw.println();
418 pw.println(" Saved user stacks:");
419 for (int i = 0; i < mUserStacks.size(); ++i) {
420 UserStacks userStacks = mUserStacks.valueAt(i);
421 pw.print(" UserId="); pw.println(Integer.toHexString(mUserStacks.keyAt(i)));
422 pw.print(" StackHistory="); pw.println(userStacks.mSavedStackHistory);
423 pw.print(" StackBox="); userStacks.mSavedStackBox.dump(" ", pw);
424 }
425 }
Craig Mautner59c00972012-07-30 12:10:24 -0700426 pw.println();
427 }
Craig Mautner858d8a62013-04-23 17:08:34 -0700428
429 private final class UserStacks {
430 final ArrayList<TaskStack> mSavedStackHistory;
431 StackBox mSavedStackBox;
432 int mBoxNdx;
433
434 public UserStacks() {
435 mSavedStackHistory = new ArrayList<TaskStack>(mStackHistory);
436 for (int stackNdx = mStackHistory.size() - 1; stackNdx >=0; --stackNdx) {
437 if (mStackHistory.get(stackNdx) != mHomeStack) {
438 mStackHistory.remove(stackNdx);
439 }
440 }
441 mSavedStackBox = null;
442 mBoxNdx = -1;
443 for (int boxNdx = mStackBoxes.size() - 1; boxNdx >= 0; --boxNdx) {
444 StackBox box = mStackBoxes.get(boxNdx);
445 if (box.mStack != mHomeStack) {
446 mSavedStackBox = box;
447 mBoxNdx = boxNdx;
448 mStackBoxes.remove(boxNdx);
449 break;
450 }
451 }
452 }
453
454 void restore() {
455 mStackHistory = mSavedStackHistory;
456 if (mBoxNdx >= 0) {
457 mStackBoxes.add(mBoxNdx, mSavedStackBox);
458 }
459 }
460 }
Craig Mautner59c00972012-07-30 12:10:24 -0700461}