blob: edf3d3bbb8ac50b4b63fa5b8df2ee4a8652ef70b [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;
21import static com.android.server.wm.WindowManagerService.TAG;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070022
Craig Mautnerc00204b2013-03-05 15:02:14 -080023import android.graphics.Rect;
Craig Mautnerde4ef022013-04-07 19:01:33 -070024import android.util.Slog;
Craig Mautnerb47bbc32012-08-22 17:41:48 -070025import android.view.Display;
Craig Mautner59c00972012-07-30 12:10:24 -070026import android.view.DisplayInfo;
27
28import java.io.PrintWriter;
29import java.util.ArrayList;
30
31class DisplayContentList extends ArrayList<DisplayContent> {
32}
33
34/**
35 * Utility class for keeping track of the WindowStates and other pertinent contents of a
36 * particular Display.
37 *
38 * IMPORTANT: No method from this class should ever be used without holding
39 * WindowManagerService.mWindowMap.
40 */
41class DisplayContent {
42
43 /** Unique identifier of this stack. */
44 private final int mDisplayId;
45
46 /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
47 * from mDisplayWindows; */
48 private WindowList mWindows = new WindowList();
49
Craig Mautner59c00972012-07-30 12:10:24 -070050 // This protects the following display size properties, so that
51 // getDisplaySize() doesn't need to acquire the global lock. This is
52 // needed because the window manager sometimes needs to use ActivityThread
53 // while it has its global state locked (for example to load animation
54 // resources), but the ActivityThread also needs get the current display
55 // size sometimes when it has its package lock held.
56 //
57 // These will only be modified with both mWindowMap and mDisplaySizeLock
58 // held (in that order) so the window manager doesn't need to acquire this
59 // lock when needing these values in its normal operation.
60 final Object mDisplaySizeLock = new Object();
61 int mInitialDisplayWidth = 0;
62 int mInitialDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -070063 int mInitialDisplayDensity = 0;
Craig Mautner59c00972012-07-30 12:10:24 -070064 int mBaseDisplayWidth = 0;
65 int mBaseDisplayHeight = 0;
Dianne Hackborndde331c2012-08-03 14:01:57 -070066 int mBaseDisplayDensity = 0;
Craig Mautner2d5618c2012-10-18 13:55:47 -070067 private final DisplayInfo mDisplayInfo = new DisplayInfo();
68 private final Display mDisplay;
Craig Mautner59c00972012-07-30 12:10:24 -070069
Craig Mautner39834192012-09-02 07:47:24 -070070 // Accessed directly by all users.
71 boolean layoutNeeded;
Craig Mautner76a71652012-09-03 23:23:58 -070072 int pendingLayoutChanges;
Craig Mautner69b08182012-09-05 13:07:13 -070073 final boolean isDefaultDisplay;
Craig Mautner39834192012-09-02 07:47:24 -070074
Craig Mautner2d5618c2012-10-18 13:55:47 -070075 /**
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080076 * Window tokens that are in the process of exiting, but still
77 * on screen for animations.
78 */
79 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
80
81 /**
82 * Application tokens that are in the process of exiting, but still
83 * on screen for animations.
84 */
85 final AppTokenList mExitingAppTokens = new AppTokenList();
86
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070087 /** Array containing the home StackBox and possibly one more which would contain apps */
Craig Mautner00af9fe2013-03-25 09:13:41 -070088 private ArrayList<StackBox> mStackBoxes = new ArrayList<StackBox>();
Craig Mautnerc00204b2013-03-05 15:02:14 -080089
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070090 /** True when the home StackBox is at the top of mStackBoxes, false otherwise */
Craig Mautnerde4ef022013-04-07 19:01:33 -070091 private TaskStack mHomeStack = null;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -070092
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080093 /**
94 * Sorted most recent at top, oldest at [0].
95 */
Craig Mautnerd9a22882013-03-16 15:00:36 -070096 ArrayList<Task> mTmpTasks = new ArrayList<Task>();
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080097
98 /**
Craig Mautner2d5618c2012-10-18 13:55:47 -070099 * @param display May not be null.
100 */
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700101 DisplayContent(Display display) {
102 mDisplay = display;
103 mDisplayId = display.getDisplayId();
104 display.getDisplayInfo(mDisplayInfo);
Craig Mautner69b08182012-09-05 13:07:13 -0700105 isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
Craig Mautner59c00972012-07-30 12:10:24 -0700106 }
107
108 int getDisplayId() {
109 return mDisplayId;
110 }
111
112 WindowList getWindowList() {
113 return mWindows;
114 }
115
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700116 Display getDisplay() {
117 return mDisplay;
118 }
119
Craig Mautner59c00972012-07-30 12:10:24 -0700120 DisplayInfo getDisplayInfo() {
121 return mDisplayInfo;
122 }
123
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700124 boolean homeOnTop() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700125 return mStackBoxes.get(0).mStack != mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700126 }
127
Craig Mautner00af9fe2013-03-25 09:13:41 -0700128 /**
129 * Retrieve the tasks on this display in stack order from the topmost TaskStack down.
130 * Note that the order of TaskStacks in the same StackBox is defined within StackBox.
131 * @return All the Tasks, in order, on this display.
132 */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800133 ArrayList<Task> getTasks() {
Craig Mautnerd9a22882013-03-16 15:00:36 -0700134 mTmpTasks.clear();
135 int numBoxes = mStackBoxes.size();
136 for (int boxNdx = 0; boxNdx < numBoxes; ++boxNdx) {
137 mTmpTasks.addAll(mStackBoxes.get(boxNdx).getTasks());
138 }
139 return mTmpTasks;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800140 }
141
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700142 TaskStack getHomeStack() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700143 return mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700144 }
145
Craig Mautner722285e2012-09-07 13:55:58 -0700146 public void updateDisplayInfo() {
147 mDisplay.getDisplayInfo(mDisplayInfo);
148 }
149
Craig Mautner00af9fe2013-03-25 09:13:41 -0700150 /** @return The number of tokens in all of the Tasks on this display. */
Craig Mautnerf81b90872013-02-26 13:02:43 -0800151 int numTokens() {
Craig Mautnerd9a22882013-03-16 15:00:36 -0700152 getTasks();
Craig Mautnerf81b90872013-02-26 13:02:43 -0800153 int count = 0;
Craig Mautnerd9a22882013-03-16 15:00:36 -0700154 for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
155 count += mTmpTasks.get(taskNdx).mAppTokens.size();
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800156 }
Craig Mautnerf81b90872013-02-26 13:02:43 -0800157 return count;
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800158 }
159
Craig Mautner00af9fe2013-03-25 09:13:41 -0700160 /** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800161 TaskStack createStack(int stackId, int relativeStackId, int position, float weight) {
162 TaskStack newStack = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700163 if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackId="
164 + relativeStackId + " position=" + position + " weight=" + weight);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800165 if (mStackBoxes.isEmpty()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700166 if (stackId != HOME_STACK_ID) {
167 throw new IllegalArgumentException("createStack: First stackId not "
168 + HOME_STACK_ID);
169 }
Craig Mautner967212c2013-04-13 21:10:58 -0700170 StackBox newBox = new StackBox(this, null);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800171 mStackBoxes.add(newBox);
Craig Mautner967212c2013-04-13 21:10:58 -0700172 newStack = new TaskStack(stackId, this);
173 newStack.mStackBox = newBox;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800174 newBox.mStack = newStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700175 mHomeStack = newStack;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800176 } else {
177 int stackBoxNdx;
178 for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
179 final StackBox box = mStackBoxes.get(stackBoxNdx);
180 if (position == StackBox.TASK_STACK_GOES_OVER
181 || position == StackBox.TASK_STACK_GOES_UNDER) {
182 // Position indicates a new box is added at top level only.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700183 if (box.contains(relativeStackId)) {
Craig Mautner967212c2013-04-13 21:10:58 -0700184 StackBox newBox = new StackBox(this, null);
185 newStack = new TaskStack(stackId, this);
186 newStack.mStackBox = newBox;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800187 newBox.mStack = newStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700188 final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
189 if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +
190 (stackBoxNdx + offset));
Craig Mautnerc00204b2013-03-05 15:02:14 -0800191 mStackBoxes.add(stackBoxNdx + offset, newBox);
192 break;
193 }
194 } else {
195 // Remaining position values indicate a box must be split.
196 newStack = box.split(stackId, relativeStackId, position, weight);
197 if (newStack != null) {
198 break;
199 }
200 }
201 }
Craig Mautner00af9fe2013-03-25 09:13:41 -0700202 if (stackBoxNdx < 0) {
203 throw new IllegalArgumentException("createStack: stackId " + relativeStackId
204 + " not found.");
Craig Mautnerc00204b2013-03-05 15:02:14 -0800205 }
206 }
Craig Mautner967212c2013-04-13 21:10:58 -0700207 if (newStack != null) {
208 layoutNeeded = true;
209 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800210 return newStack;
211 }
212
Craig Mautner00af9fe2013-03-25 09:13:41 -0700213 /** Refer to {@link WindowManagerService#resizeStack(int, float)} */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800214 boolean resizeStack(int stackId, float weight) {
Craig Mautner967212c2013-04-13 21:10:58 -0700215 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
Craig Mautnerc00204b2013-03-05 15:02:14 -0800216 final StackBox box = mStackBoxes.get(stackBoxNdx);
217 if (box.resize(stackId, weight)) {
218 return true;
219 }
220 }
221 return false;
222 }
223
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700224 void removeStackBox(StackBox box) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700225 if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700226 final TaskStack stack = box.mStack;
227 if (stack != null && stack.mStackId == HOME_STACK_ID) {
228 // Never delete the home stack, even if it is empty.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700229 if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack.");
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700230 return;
231 }
232 mStackBoxes.remove(box);
233 }
234
Craig Mautner00af9fe2013-03-25 09:13:41 -0700235 /**
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700236 * Move the home StackBox to the top or bottom of mStackBoxes. That is the only place
237 * it is allowed to be. This is a nop if the home StackBox is already in the correct position.
238 * @param toTop Move home to the top of mStackBoxes if true, to the bottom if false.
239 * @return true if a change was made, false otherwise.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700240 */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700241 boolean moveHomeStackBox(boolean toTop) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700242 if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop);
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700243 switch (mStackBoxes.size()) {
244 case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
245 case 1: return false; // Only the home StackBox exists.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700246 case 2:
247 if (homeOnTop() ^ toTop) {
248 mStackBoxes.add(mStackBoxes.remove(0));
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700249 return true;
250 }
251 return false;
252 default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!");
Craig Mautner00af9fe2013-03-25 09:13:41 -0700253 }
254 }
255
Craig Mautner967212c2013-04-13 21:10:58 -0700256 /**
257 * Propagate the new bounds to all child stack boxes, applying weights as we move down.
258 * @param contentRect The bounds to apply at the top level.
259 */
260 void setStackBoxSize(Rect contentRect) {
261 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
262 mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect);
263 }
264 }
265
266 Rect getStackBounds(int stackId) {
267 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
268 Rect bounds = mStackBoxes.get(stackBoxNdx).getStackBounds(stackId);
269 if (bounds != null) {
270 return bounds;
271 }
272 }
273 return null;
274 }
275
Craig Mautnera91f9e22012-09-14 16:22:08 -0700276 public void dump(String prefix, PrintWriter pw) {
277 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
278 final String subPrefix = " " + prefix;
279 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
280 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
281 pw.print("dpi");
282 if (mInitialDisplayWidth != mBaseDisplayWidth
283 || mInitialDisplayHeight != mBaseDisplayHeight
284 || mInitialDisplayDensity != mBaseDisplayDensity) {
285 pw.print(" base=");
286 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
287 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
288 }
289 pw.print(" cur=");
290 pw.print(mDisplayInfo.logicalWidth);
291 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
292 pw.print(" app=");
293 pw.print(mDisplayInfo.appWidth);
294 pw.print("x"); pw.print(mDisplayInfo.appHeight);
295 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
296 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
297 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
298 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Dianne Hackbornc652de82013-02-15 16:32:56 -0800299 pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700300 for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
301 pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
302 mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
303 }
304 int ndx = numTokens();
305 if (ndx > 0) {
306 pw.println();
307 pw.println(" Application tokens in Z order:");
308 getTasks();
309 for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
310 AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
311 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
312 final AppWindowToken wtoken = tokens.get(tokenNdx);
313 pw.print(" App #"); pw.print(ndx--);
314 pw.print(' '); pw.print(wtoken); pw.println(":");
315 wtoken.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800316 }
317 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700318 }
319 if (mExitingTokens.size() > 0) {
320 pw.println();
321 pw.println(" Exiting tokens:");
322 for (int i=mExitingTokens.size()-1; i>=0; i--) {
323 WindowToken token = mExitingTokens.get(i);
324 pw.print(" Exiting #"); pw.print(i);
325 pw.print(' '); pw.print(token);
326 pw.println(':');
327 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800328 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700329 }
330 if (mExitingAppTokens.size() > 0) {
331 pw.println();
332 pw.println(" Exiting application tokens:");
333 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
334 WindowToken token = mExitingAppTokens.get(i);
335 pw.print(" Exiting App #"); pw.print(i);
336 pw.print(' '); pw.print(token);
337 pw.println(':');
338 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800339 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700340 }
Craig Mautner59c00972012-07-30 12:10:24 -0700341 pw.println();
342 }
343}