blob: 43a5f0c345e675911b1130be4b617af2f68193bc [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 Mautner05d6272ba2013-02-11 09:39:27 -080019import android.os.Debug;
20import android.util.Slog;
Craig Mautnerb1fd65c02013-02-05 13:34:57 -080021import android.util.SparseArray;
Craig Mautnerb47bbc32012-08-22 17:41:48 -070022import android.view.Display;
Craig Mautner59c00972012-07-30 12:10:24 -070023import android.view.DisplayInfo;
24
25import java.io.PrintWriter;
26import java.util.ArrayList;
Craig Mautner05d6272ba2013-02-11 09:39:27 -080027import java.util.Iterator;
28import java.util.NoSuchElementException;
Craig Mautner59c00972012-07-30 12:10:24 -070029
30class DisplayContentList extends ArrayList<DisplayContent> {
31}
32
33/**
34 * Utility class for keeping track of the WindowStates and other pertinent contents of a
35 * particular Display.
36 *
37 * IMPORTANT: No method from this class should ever be used without holding
38 * WindowManagerService.mWindowMap.
39 */
40class DisplayContent {
Craig Mautner05d6272ba2013-02-11 09:39:27 -080041 private final static String TAG = "DisplayContent";
Craig Mautner59c00972012-07-30 12:10:24 -070042
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 * List controlling the ordering of windows in different applications which must
77 * be kept in sync with ActivityManager.
78 */
79 final AppTokenList mAppTokens = new AppTokenList();
80
81 /**
82 * AppWindowTokens in the Z order they were in at the start of an animation. Between
83 * animations this list is maintained in the exact order of mAppTokens. If tokens
84 * are added to mAppTokens during an animation an attempt is made to insert them at the same
85 * logical location in this list. Note that this list is always in sync with mWindows.
86 */
87 AppTokenList mAnimatingAppTokens = new AppTokenList();
88
89 /**
90 * Window tokens that are in the process of exiting, but still
91 * on screen for animations.
92 */
93 final ArrayList<WindowToken> mExitingTokens = new ArrayList<WindowToken>();
94
95 /**
96 * Application tokens that are in the process of exiting, but still
97 * on screen for animations.
98 */
99 final AppTokenList mExitingAppTokens = new AppTokenList();
100
101 /**
102 * Sorted most recent at top, oldest at [0].
103 */
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800104 ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800105 SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>();
106
107 /**
Craig Mautner2d5618c2012-10-18 13:55:47 -0700108 * @param display May not be null.
109 */
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700110 DisplayContent(Display display) {
111 mDisplay = display;
112 mDisplayId = display.getDisplayId();
113 display.getDisplayInfo(mDisplayInfo);
Craig Mautner69b08182012-09-05 13:07:13 -0700114 isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
Craig Mautner59c00972012-07-30 12:10:24 -0700115 }
116
117 int getDisplayId() {
118 return mDisplayId;
119 }
120
121 WindowList getWindowList() {
122 return mWindows;
123 }
124
Craig Mautnerb47bbc32012-08-22 17:41:48 -0700125 Display getDisplay() {
126 return mDisplay;
127 }
128
Craig Mautner59c00972012-07-30 12:10:24 -0700129 DisplayInfo getDisplayInfo() {
130 return mDisplayInfo;
131 }
132
Craig Mautner722285e2012-09-07 13:55:58 -0700133 public void updateDisplayInfo() {
134 mDisplay.getDisplayInfo(mDisplayInfo);
135 }
136
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800137 /**
138 * Find the location to insert a new AppWindowToken into the window-ordered app token list.
139 * @param addPos The location the token was inserted into in mAppTokens.
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800140 * @param wtoken The token to insert.
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800141 */
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800142 void addAppToken(final int addPos, final AppWindowToken wtoken) {
143 mAppTokens.add(addPos, wtoken);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800144
145 if (addPos == 0 || addPos == mAnimatingAppTokens.size()) {
146 // It was inserted into the beginning or end of mAppTokens. Honor that.
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800147 mAnimatingAppTokens.add(addPos, wtoken);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800148 } else {
149 // Find the item immediately above the mAppTokens insertion point and put the token
150 // immediately below that one in mAnimatingAppTokens.
151 final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1);
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800152 mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800153 }
154
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800155 TaskList task = mTaskIdToTaskList.get(wtoken.groupId);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800156 if (task == null) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800157 task = new TaskList(wtoken, this);
158 mTaskIdToTaskList.put(wtoken.groupId, task);
159 mTaskLists.add(task);
160 } else {
161 task.mAppTokens.add(wtoken);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800162 }
163 }
164
165 void removeAppToken(final AppWindowToken wtoken) {
166 mAppTokens.remove(wtoken);
167 mAnimatingAppTokens.remove(wtoken);
168 final int taskId = wtoken.groupId;
169 final TaskList task = mTaskIdToTaskList.get(taskId);
170 if (task != null) {
171 AppTokenList appTokens = task.mAppTokens;
172 appTokens.remove(wtoken);
173 if (appTokens.size() == 0) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800174 mTaskLists.remove(task);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800175 mTaskIdToTaskList.delete(taskId);
176 }
177 }
178 }
179
180 void refillAnimatingAppTokens() {
181 mAnimatingAppTokens.clear();
182 mAnimatingAppTokens.addAll(mAppTokens);
183 }
184
185 void setAppTaskId(AppWindowToken wtoken, int newTaskId) {
186 final int taskId = wtoken.groupId;
187 TaskList task = mTaskIdToTaskList.get(taskId);
188 if (task != null) {
189 AppTokenList appTokens = task.mAppTokens;
190 appTokens.remove(wtoken);
191 if (appTokens.size() == 0) {
192 mTaskIdToTaskList.delete(taskId);
193 }
194 }
195
196 task = mTaskIdToTaskList.get(newTaskId);
197 if (task == null) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800198 task = new TaskList(wtoken, this);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800199 mTaskIdToTaskList.put(newTaskId, task);
200 } else {
201 task.mAppTokens.add(wtoken);
202 }
203
204 wtoken.groupId = newTaskId;
205 }
206
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800207 class TaskListsIterator implements Iterator<TaskList> {
208 private int mCur;
209 private boolean mReverse;
210
211 TaskListsIterator() {
212 this(false);
213 }
214
215 TaskListsIterator(boolean reverse) {
216 mReverse = reverse;
217 int numTaskLists = mTaskLists.size();
218 mCur = reverse ? numTaskLists - 1 : 0;
219 }
220
221 @Override
222 public boolean hasNext() {
223 if (mReverse) {
224 return mCur >= 0;
225 }
226 return mCur < mTaskLists.size();
227 }
228
229 @Override
230 public TaskList next() {
231 if (hasNext()) {
232 TaskList taskList = mTaskLists.get(mCur);
233 mCur += (mReverse ? -1 : 1);
234 return taskList;
235 }
236 throw new NoSuchElementException();
237 }
238
239 @Override
240 public void remove() {
241 throw new IllegalArgumentException();
242 }
243 }
244
245 class AppTokenIterator implements Iterator<AppWindowToken> {
246 final TaskListsIterator mIterator;
247 final boolean mReverse;
248 int mCur;
249 TaskList mTaskList;
250
251 public AppTokenIterator() {
252 this(false);
253 }
254
255 public AppTokenIterator(boolean reverse) {
256 mReverse = reverse;
257 mIterator = new TaskListsIterator(reverse);
258 getNextTaskList();
259 }
260
261 private void getNextTaskList() {
262 if (mIterator.hasNext()) {
263 mTaskList = mIterator.next();
264 mCur = mReverse ? mTaskList.mAppTokens.size() - 1 : 0;
265 }
266 }
267
268 @Override
269 public boolean hasNext() {
270 if (mTaskList == null) {
271 return false;
272 }
273 if (mReverse) {
274 return mCur >= 0;
275 }
276 return mCur < mTaskList.mAppTokens.size();
277 }
278
279 @Override
280 public AppWindowToken next() {
281 if (hasNext()) {
282 AppWindowToken wtoken = mTaskList.mAppTokens.get(mCur);
283 mCur += mReverse ? -1 : 1;
284 if (!hasNext()) {
285 getNextTaskList();
286 }
287 return wtoken;
288 }
289 throw new NoSuchElementException();
290 }
291
292 @Override
293 public void remove() {
294 throw new IllegalArgumentException();
295 }
296 }
297
298 void verifyAppTokens() {
299 AppTokenIterator iterator = new AppTokenIterator();
300 for (int i = 0; i < mAppTokens.size(); ++i) {
301 if (!iterator.hasNext()) {
302 Slog.e(TAG, "compareAppTokens: More mAppTokens than TaskList tokens. Callers="
303 + Debug.getCallers(4));
304 while (i < mAppTokens.size()) {
305 Slog.e(TAG, "compareAppTokens: mAppTokens[" + i + "]=" + mAppTokens.get(i));
306 i++;
307 }
308 return;
309 }
310 AppWindowToken appToken = mAppTokens.get(i);
311 AppWindowToken taskListToken = iterator.next();
312 if (appToken != taskListToken) {
313 Slog.e(TAG, "compareAppTokens: Mismatch at " + i + " appToken=" + appToken
314 + " taskListToken=" + taskListToken + ". Callers=" + Debug.getCallers(4));
315 }
316 }
317 if (iterator.hasNext()) {
318 Slog.e(TAG, "compareAppTokens: More TaskList tokens than mAppTokens Callers="
319 + Debug.getCallers(4));
320 }
321 }
322
Craig Mautnera91f9e22012-09-14 16:22:08 -0700323 public void dump(String prefix, PrintWriter pw) {
324 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
325 final String subPrefix = " " + prefix;
326 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
327 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
328 pw.print("dpi");
329 if (mInitialDisplayWidth != mBaseDisplayWidth
330 || mInitialDisplayHeight != mBaseDisplayHeight
331 || mInitialDisplayDensity != mBaseDisplayDensity) {
332 pw.print(" base=");
333 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
334 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
335 }
336 pw.print(" cur=");
337 pw.print(mDisplayInfo.logicalWidth);
338 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
339 pw.print(" app=");
340 pw.print(mDisplayInfo.appWidth);
341 pw.print("x"); pw.print(mDisplayInfo.appHeight);
342 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
343 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
344 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
345 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800346 if (mAppTokens.size() > 0) {
347 pw.println();
348 pw.println(" Application tokens in Z order:");
349 for (int i=mAppTokens.size()-1; i>=0; i--) {
350 pw.print(" App #"); pw.print(i);
351 pw.print(' '); pw.print(mAppTokens.get(i)); pw.println(":");
352 mAppTokens.get(i).dump(pw, " ");
353 }
354 }
355 if (mExitingTokens.size() > 0) {
356 pw.println();
357 pw.println(" Exiting tokens:");
358 for (int i=mExitingTokens.size()-1; i>=0; i--) {
359 WindowToken token = mExitingTokens.get(i);
360 pw.print(" Exiting #"); pw.print(i);
361 pw.print(' '); pw.print(token);
362 pw.println(':');
363 token.dump(pw, " ");
364 }
365 }
366 if (mExitingAppTokens.size() > 0) {
367 pw.println();
368 pw.println(" Exiting application tokens:");
369 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
370 WindowToken token = mExitingAppTokens.get(i);
371 pw.print(" Exiting App #"); pw.print(i);
372 pw.print(' '); pw.print(token);
373 pw.println(':');
374 token.dump(pw, " ");
375 }
376 }
377 if (mTaskIdToTaskList.size() > 0) {
378 pw.println();
379 for (int i = 0; i < mTaskIdToTaskList.size(); ++i) {
380 pw.print(" TaskList #"); pw.print(i);
381 pw.print(" taskId="); pw.println(mTaskIdToTaskList.keyAt(i));
382 pw.print(" mAppTokens=");
383 pw.println(mTaskIdToTaskList.valueAt(i).mAppTokens);
384 pw.println();
385 }
386 }
387 pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
Craig Mautner59c00972012-07-30 12:10:24 -0700388 pw.println();
389 }
390}