blob: f8e779debd6c7b2dfd73a74346c78300c25bf42c [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();
Craig Mautner926f3832013-02-13 11:56:07 -0800182 AppTokenIterator iterator = new AppTokenIterator();
183 while (iterator.hasNext()) {
184 mAnimatingAppTokens.add(iterator.next());
185 }
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800186 }
187
188 void setAppTaskId(AppWindowToken wtoken, int newTaskId) {
189 final int taskId = wtoken.groupId;
190 TaskList task = mTaskIdToTaskList.get(taskId);
191 if (task != null) {
192 AppTokenList appTokens = task.mAppTokens;
193 appTokens.remove(wtoken);
194 if (appTokens.size() == 0) {
195 mTaskIdToTaskList.delete(taskId);
196 }
197 }
198
199 task = mTaskIdToTaskList.get(newTaskId);
200 if (task == null) {
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800201 task = new TaskList(wtoken, this);
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800202 mTaskIdToTaskList.put(newTaskId, task);
203 } else {
204 task.mAppTokens.add(wtoken);
205 }
206
207 wtoken.groupId = newTaskId;
208 }
209
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800210 class TaskListsIterator implements Iterator<TaskList> {
211 private int mCur;
212 private boolean mReverse;
213
214 TaskListsIterator() {
215 this(false);
216 }
217
218 TaskListsIterator(boolean reverse) {
219 mReverse = reverse;
220 int numTaskLists = mTaskLists.size();
221 mCur = reverse ? numTaskLists - 1 : 0;
222 }
223
224 @Override
225 public boolean hasNext() {
226 if (mReverse) {
227 return mCur >= 0;
228 }
229 return mCur < mTaskLists.size();
230 }
231
232 @Override
233 public TaskList next() {
234 if (hasNext()) {
235 TaskList taskList = mTaskLists.get(mCur);
236 mCur += (mReverse ? -1 : 1);
237 return taskList;
238 }
239 throw new NoSuchElementException();
240 }
241
242 @Override
243 public void remove() {
244 throw new IllegalArgumentException();
245 }
246 }
247
248 class AppTokenIterator implements Iterator<AppWindowToken> {
249 final TaskListsIterator mIterator;
250 final boolean mReverse;
251 int mCur;
252 TaskList mTaskList;
253
254 public AppTokenIterator() {
255 this(false);
256 }
257
258 public AppTokenIterator(boolean reverse) {
259 mReverse = reverse;
260 mIterator = new TaskListsIterator(reverse);
261 getNextTaskList();
262 }
263
264 private void getNextTaskList() {
265 if (mIterator.hasNext()) {
266 mTaskList = mIterator.next();
267 mCur = mReverse ? mTaskList.mAppTokens.size() - 1 : 0;
268 }
269 }
270
271 @Override
272 public boolean hasNext() {
273 if (mTaskList == null) {
274 return false;
275 }
276 if (mReverse) {
277 return mCur >= 0;
278 }
279 return mCur < mTaskList.mAppTokens.size();
280 }
281
282 @Override
283 public AppWindowToken next() {
284 if (hasNext()) {
285 AppWindowToken wtoken = mTaskList.mAppTokens.get(mCur);
286 mCur += mReverse ? -1 : 1;
287 if (!hasNext()) {
288 getNextTaskList();
289 }
290 return wtoken;
291 }
292 throw new NoSuchElementException();
293 }
294
295 @Override
296 public void remove() {
297 throw new IllegalArgumentException();
298 }
Craig Mautner30e2d722013-02-12 11:30:16 -0800299
300 int size() {
301 int size = 0;
302 final TaskListsIterator iterator = new TaskListsIterator();
303 while (iterator.hasNext()) {
304 size += iterator.next().mAppTokens.size();
305 }
306 return size;
307 }
Craig Mautner05d6272ba2013-02-11 09:39:27 -0800308 }
309
310 void verifyAppTokens() {
311 AppTokenIterator iterator = new AppTokenIterator();
312 for (int i = 0; i < mAppTokens.size(); ++i) {
313 if (!iterator.hasNext()) {
314 Slog.e(TAG, "compareAppTokens: More mAppTokens than TaskList tokens. Callers="
315 + Debug.getCallers(4));
316 while (i < mAppTokens.size()) {
317 Slog.e(TAG, "compareAppTokens: mAppTokens[" + i + "]=" + mAppTokens.get(i));
318 i++;
319 }
320 return;
321 }
322 AppWindowToken appToken = mAppTokens.get(i);
323 AppWindowToken taskListToken = iterator.next();
324 if (appToken != taskListToken) {
325 Slog.e(TAG, "compareAppTokens: Mismatch at " + i + " appToken=" + appToken
326 + " taskListToken=" + taskListToken + ". Callers=" + Debug.getCallers(4));
327 }
328 }
329 if (iterator.hasNext()) {
330 Slog.e(TAG, "compareAppTokens: More TaskList tokens than mAppTokens Callers="
331 + Debug.getCallers(4));
332 }
333 }
334
Craig Mautnera91f9e22012-09-14 16:22:08 -0700335 public void dump(String prefix, PrintWriter pw) {
336 pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
337 final String subPrefix = " " + prefix;
338 pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
339 pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
340 pw.print("dpi");
341 if (mInitialDisplayWidth != mBaseDisplayWidth
342 || mInitialDisplayHeight != mBaseDisplayHeight
343 || mInitialDisplayDensity != mBaseDisplayDensity) {
344 pw.print(" base=");
345 pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
346 pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
347 }
348 pw.print(" cur=");
349 pw.print(mDisplayInfo.logicalWidth);
350 pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
351 pw.print(" app=");
352 pw.print(mDisplayInfo.appWidth);
353 pw.print("x"); pw.print(mDisplayInfo.appHeight);
354 pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
355 pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
356 pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
357 pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
Craig Mautner926f3832013-02-13 11:56:07 -0800358 AppTokenIterator iterator = new AppTokenIterator(true);
359 int ndx = iterator.size() - 1;
360 if (ndx >= 0) {
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800361 pw.println();
362 pw.println(" Application tokens in Z order:");
Craig Mautner926f3832013-02-13 11:56:07 -0800363 while (iterator.hasNext()) {
364 AppWindowToken wtoken = iterator.next();
365 pw.print(" App #"); pw.print(ndx--);
366 pw.print(' '); pw.print(wtoken); pw.println(":");
367 wtoken.dump(pw, " ");
Craig Mautnerb1fd65c02013-02-05 13:34:57 -0800368 }
369 }
370 if (mExitingTokens.size() > 0) {
371 pw.println();
372 pw.println(" Exiting tokens:");
373 for (int i=mExitingTokens.size()-1; i>=0; i--) {
374 WindowToken token = mExitingTokens.get(i);
375 pw.print(" Exiting #"); pw.print(i);
376 pw.print(' '); pw.print(token);
377 pw.println(':');
378 token.dump(pw, " ");
379 }
380 }
381 if (mExitingAppTokens.size() > 0) {
382 pw.println();
383 pw.println(" Exiting application tokens:");
384 for (int i=mExitingAppTokens.size()-1; i>=0; i--) {
385 WindowToken token = mExitingAppTokens.get(i);
386 pw.print(" Exiting App #"); pw.print(i);
387 pw.print(' '); pw.print(token);
388 pw.println(':');
389 token.dump(pw, " ");
390 }
391 }
392 if (mTaskIdToTaskList.size() > 0) {
393 pw.println();
394 for (int i = 0; i < mTaskIdToTaskList.size(); ++i) {
395 pw.print(" TaskList #"); pw.print(i);
396 pw.print(" taskId="); pw.println(mTaskIdToTaskList.keyAt(i));
397 pw.print(" mAppTokens=");
398 pw.println(mTaskIdToTaskList.valueAt(i).mAppTokens);
399 pw.println();
400 }
401 }
402 pw.print(subPrefix); pw.print("layoutNeeded="); pw.println(layoutNeeded);
Craig Mautner59c00972012-07-30 12:10:24 -0700403 pw.println();
404 }
405}