blob: 915c696c52ebe2cf9c49b0d98680dd79d90f137c [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 Mautner4cd0c13f2013-04-16 15:55:52 -070093 /** Save allocating when retrieving tasks */
Craig Mautnerd9a22882013-03-16 15:00:36 -070094 ArrayList<Task> mTmpTasks = new ArrayList<Task>();
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080095
Craig Mautner4cd0c13f2013-04-16 15:55:52 -070096 /** Sorted most recent at top, oldest at [0]. */
97 ArrayList<TaskStack> mStackHistory = new ArrayList<TaskStack>();
98
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080099 /**
Craig Mautner2d5618c2012-10-18 13:55:47 -0700100 * @param display May not be null.
101 */
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700102 DisplayContent(Display display) {
103 mDisplay = display;
104 mDisplayId = display.getDisplayId();
105 display.getDisplayInfo(mDisplayInfo);
Craig Mautner69b08182012-09-05 13:07:13 -0700106 isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
Craig Mautner59c00972012-07-30 12:10:24 -0700107 }
108
109 int getDisplayId() {
110 return mDisplayId;
111 }
112
113 WindowList getWindowList() {
114 return mWindows;
115 }
116
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700117 Display getDisplay() {
118 return mDisplay;
119 }
120
Craig Mautner59c00972012-07-30 12:10:24 -0700121 DisplayInfo getDisplayInfo() {
122 return mDisplayInfo;
123 }
124
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700125 boolean homeOnTop() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700126 return mStackBoxes.get(0).mStack != mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700127 }
128
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700129 void moveStack(TaskStack stack, boolean toTop) {
130 mStackHistory.remove(stack);
131 mStackHistory.add(toTop ? mStackHistory.size() : 0, stack);
132 }
133
Craig Mautner00af9fe2013-03-25 09:13:41 -0700134 /**
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700135 * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700136 * @return All the Tasks, in order, on this display.
137 */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800138 ArrayList<Task> getTasks() {
Craig Mautnerd9a22882013-03-16 15:00:36 -0700139 mTmpTasks.clear();
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700140 final int numStacks = mStackHistory.size();
141 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
142 mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
Craig Mautnerd9a22882013-03-16 15:00:36 -0700143 }
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700144 if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" +
145 mStackHistory);
Craig Mautnerd9a22882013-03-16 15:00:36 -0700146 return mTmpTasks;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800147 }
148
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700149 TaskStack getHomeStack() {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700150 return mHomeStack;
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700151 }
152
Craig Mautner722285e2012-09-07 13:55:58 -0700153 public void updateDisplayInfo() {
154 mDisplay.getDisplayInfo(mDisplayInfo);
155 }
156
Craig Mautner00af9fe2013-03-25 09:13:41 -0700157 /** @return The number of tokens in all of the Tasks on this display. */
Craig Mautnerf81b90872013-02-26 13:02:43 -0800158 int numTokens() {
Craig Mautnerd9a22882013-03-16 15:00:36 -0700159 getTasks();
Craig Mautnerf81b90872013-02-26 13:02:43 -0800160 int count = 0;
Craig Mautnerd9a22882013-03-16 15:00:36 -0700161 for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
162 count += mTmpTasks.get(taskNdx).mAppTokens.size();
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800163 }
Craig Mautnerf81b90872013-02-26 13:02:43 -0800164 return count;
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800165 }
166
Craig Mautner00af9fe2013-03-25 09:13:41 -0700167 /** Refer to {@link WindowManagerService#createStack(int, int, int, float)} */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800168 TaskStack createStack(int stackId, int relativeStackId, int position, float weight) {
169 TaskStack newStack = null;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700170 if (DEBUG_STACK) Slog.d(TAG, "createStack: stackId=" + stackId + " relativeStackId="
171 + relativeStackId + " position=" + position + " weight=" + weight);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800172 if (mStackBoxes.isEmpty()) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700173 if (stackId != HOME_STACK_ID) {
174 throw new IllegalArgumentException("createStack: First stackId not "
175 + HOME_STACK_ID);
176 }
Craig Mautner967212c2013-04-13 21:10:58 -0700177 StackBox newBox = new StackBox(this, null);
Craig Mautnerc00204b2013-03-05 15:02:14 -0800178 mStackBoxes.add(newBox);
Craig Mautner967212c2013-04-13 21:10:58 -0700179 newStack = new TaskStack(stackId, this);
180 newStack.mStackBox = newBox;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800181 newBox.mStack = newStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700182 mHomeStack = newStack;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800183 } else {
184 int stackBoxNdx;
185 for (stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
186 final StackBox box = mStackBoxes.get(stackBoxNdx);
187 if (position == StackBox.TASK_STACK_GOES_OVER
188 || position == StackBox.TASK_STACK_GOES_UNDER) {
189 // Position indicates a new box is added at top level only.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700190 if (box.contains(relativeStackId)) {
Craig Mautner967212c2013-04-13 21:10:58 -0700191 StackBox newBox = new StackBox(this, null);
192 newStack = new TaskStack(stackId, this);
193 newStack.mStackBox = newBox;
Craig Mautnerc00204b2013-03-05 15:02:14 -0800194 newBox.mStack = newStack;
Craig Mautnerde4ef022013-04-07 19:01:33 -0700195 final int offset = position == StackBox.TASK_STACK_GOES_OVER ? 1 : 0;
196 if (DEBUG_STACK) Slog.d(TAG, "createStack: inserting stack at " +
197 (stackBoxNdx + offset));
Craig Mautnerc00204b2013-03-05 15:02:14 -0800198 mStackBoxes.add(stackBoxNdx + offset, newBox);
199 break;
200 }
201 } else {
202 // Remaining position values indicate a box must be split.
203 newStack = box.split(stackId, relativeStackId, position, weight);
204 if (newStack != null) {
205 break;
206 }
207 }
208 }
Craig Mautner00af9fe2013-03-25 09:13:41 -0700209 if (stackBoxNdx < 0) {
210 throw new IllegalArgumentException("createStack: stackId " + relativeStackId
211 + " not found.");
Craig Mautnerc00204b2013-03-05 15:02:14 -0800212 }
213 }
Craig Mautner967212c2013-04-13 21:10:58 -0700214 if (newStack != null) {
215 layoutNeeded = true;
216 }
Craig Mautnerc00204b2013-03-05 15:02:14 -0800217 return newStack;
218 }
219
Craig Mautner00af9fe2013-03-25 09:13:41 -0700220 /** Refer to {@link WindowManagerService#resizeStack(int, float)} */
Craig Mautnerc00204b2013-03-05 15:02:14 -0800221 boolean resizeStack(int stackId, float weight) {
Craig Mautner967212c2013-04-13 21:10:58 -0700222 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
Craig Mautnerc00204b2013-03-05 15:02:14 -0800223 final StackBox box = mStackBoxes.get(stackBoxNdx);
224 if (box.resize(stackId, weight)) {
225 return true;
226 }
227 }
228 return false;
229 }
230
Craig Mautner4cd0c13f2013-04-16 15:55:52 -0700231 void addStackBox(StackBox box, boolean toTop) {
232 if (mStackBoxes.size() >= 2) {
233 throw new RuntimeException("addStackBox: Too many toplevel StackBoxes!");
234 }
235 mStackBoxes.add(toTop ? mStackBoxes.size() : 0, box);
236 }
237
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700238 void removeStackBox(StackBox box) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700239 if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: box=" + box);
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700240 final TaskStack stack = box.mStack;
241 if (stack != null && stack.mStackId == HOME_STACK_ID) {
242 // Never delete the home stack, even if it is empty.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700243 if (DEBUG_STACK) Slog.d(TAG, "removeStackBox: Not deleting home stack.");
Craig Mautner9e4f28c2013-04-03 10:53:23 -0700244 return;
245 }
246 mStackBoxes.remove(box);
247 }
248
Craig Mautner00af9fe2013-03-25 09:13:41 -0700249 /**
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700250 * Move the home StackBox to the top or bottom of mStackBoxes. That is the only place
251 * it is allowed to be. This is a nop if the home StackBox is already in the correct position.
252 * @param toTop Move home to the top of mStackBoxes if true, to the bottom if false.
253 * @return true if a change was made, false otherwise.
Craig Mautner00af9fe2013-03-25 09:13:41 -0700254 */
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700255 boolean moveHomeStackBox(boolean toTop) {
Craig Mautnerde4ef022013-04-07 19:01:33 -0700256 if (DEBUG_STACK) Slog.d(TAG, "moveHomeStackBox: toTop=" + toTop);
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700257 switch (mStackBoxes.size()) {
258 case 0: throw new RuntimeException("moveHomeStackBox: No home StackBox!");
259 case 1: return false; // Only the home StackBox exists.
Craig Mautnerde4ef022013-04-07 19:01:33 -0700260 case 2:
261 if (homeOnTop() ^ toTop) {
262 mStackBoxes.add(mStackBoxes.remove(0));
Craig Mautnerd5d5d0f2013-04-03 15:08:21 -0700263 return true;
264 }
265 return false;
266 default: throw new RuntimeException("moveHomeStackBox: Too many toplevel StackBoxes!");
Craig Mautner00af9fe2013-03-25 09:13:41 -0700267 }
268 }
269
Craig Mautner967212c2013-04-13 21:10:58 -0700270 /**
271 * Propagate the new bounds to all child stack boxes, applying weights as we move down.
272 * @param contentRect The bounds to apply at the top level.
273 */
274 void setStackBoxSize(Rect contentRect) {
275 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
276 mStackBoxes.get(stackBoxNdx).setStackBoxSizes(contentRect);
277 }
278 }
279
280 Rect getStackBounds(int stackId) {
281 for (int stackBoxNdx = mStackBoxes.size() - 1; stackBoxNdx >= 0; --stackBoxNdx) {
282 Rect bounds = mStackBoxes.get(stackBoxNdx).getStackBounds(stackId);
283 if (bounds != null) {
284 return bounds;
285 }
286 }
287 return null;
288 }
289
Craig Mautnera91f9e22012-09-14 16:22:08 -0700290 public void dump(String prefix, PrintWriter pw) {
291 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
292 final String subPrefix = " " + prefix;
293 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
294 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
295 pw.print("dpi");
296 if (mInitialDisplayWidth != mBaseDisplayWidth
297 || mInitialDisplayHeight != mBaseDisplayHeight
298 || mInitialDisplayDensity != mBaseDisplayDensity) {
299 pw.print(" base=");
300 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
301 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
302 }
303 pw.print(" cur=");
304 pw.print(mDisplayInfo.logicalWidth);
305 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
306 pw.print(" app=");
307 pw.print(mDisplayInfo.appWidth);
308 pw.print("x"); pw.print(mDisplayInfo.appHeight);
309 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
310 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
311 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
312 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Dianne Hackbornc652de82013-02-15 16:32:56 -0800313 pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
Craig Mautnerde4ef022013-04-07 19:01:33 -0700314 for (int boxNdx = 0; boxNdx < mStackBoxes.size(); ++boxNdx) {
315 pw.print(prefix); pw.print("StackBox #"); pw.println(boxNdx);
316 mStackBoxes.get(boxNdx).dump(prefix + " ", pw);
317 }
318 int ndx = numTokens();
319 if (ndx > 0) {
320 pw.println();
321 pw.println(" Application tokens in Z order:");
322 getTasks();
323 for (int taskNdx = mTmpTasks.size() - 1; taskNdx >= 0; --taskNdx) {
324 AppTokenList tokens = mTmpTasks.get(taskNdx).mAppTokens;
325 for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
326 final AppWindowToken wtoken = tokens.get(tokenNdx);
327 pw.print(" App #"); pw.print(ndx--);
328 pw.print(' '); pw.print(wtoken); pw.println(":");
329 wtoken.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800330 }
331 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700332 }
333 if (mExitingTokens.size() > 0) {
334 pw.println();
335 pw.println(" Exiting tokens:");
336 for (int i=mExitingTokens.size()-1; i>=0; i--) {
337 WindowToken token = mExitingTokens.get(i);
338 pw.print(" Exiting #"); pw.print(i);
339 pw.print(' '); pw.print(token);
340 pw.println(':');
341 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800342 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700343 }
344 if (mExitingAppTokens.size() > 0) {
345 pw.println();
346 pw.println(" Exiting application tokens:");
347 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
348 WindowToken token = mExitingAppTokens.get(i);
349 pw.print(" Exiting App #"); pw.print(i);
350 pw.print(' '); pw.print(token);
351 pw.println(':');
352 token.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800353 }
Craig Mautnerde4ef022013-04-07 19:01:33 -0700354 }
Craig Mautner59c00972012-07-30 12:10:24 -0700355 pw.println();
356 }
357}