DisplayContent.java revision 9adfe5776d42c9ddfd4394958993304c9d355229
1/*
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
19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
23import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
24import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
26import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
27import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
28import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
29import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
30import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
31import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
32import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
33import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
34import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
35import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
36import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
37import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
38import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
39import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
40import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
41import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
42
43import android.app.ActivityManager.StackId;
44import android.graphics.Rect;
45import android.graphics.Region;
46import android.graphics.Region.Op;
47import android.hardware.display.DisplayManagerInternal;
48import android.os.Debug;
49import android.util.DisplayMetrics;
50import android.util.Slog;
51import android.view.Display;
52import android.view.DisplayInfo;
53import android.view.IWindow;
54import android.view.Surface;
55import android.view.animation.Animation;
56import com.android.internal.util.FastPrintWriter;
57
58import java.io.PrintWriter;
59import java.io.StringWriter;
60import java.util.ArrayList;
61import java.util.Arrays;
62
63class DisplayContentList extends ArrayList<DisplayContent> {
64}
65
66/**
67 * Utility class for keeping track of the WindowStates and other pertinent contents of a
68 * particular Display.
69 *
70 * IMPORTANT: No method from this class should ever be used without holding
71 * WindowManagerService.mWindowMap.
72 */
73class DisplayContent {
74
75    /** Unique identifier of this stack. */
76    private final int mDisplayId;
77
78    /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
79     * from mDisplayWindows; */
80    private final WindowList mWindows = new WindowList();
81
82    int mInitialDisplayWidth = 0;
83    int mInitialDisplayHeight = 0;
84    int mInitialDisplayDensity = 0;
85    int mBaseDisplayWidth = 0;
86    int mBaseDisplayHeight = 0;
87    int mBaseDisplayDensity = 0;
88    boolean mDisplayScalingDisabled;
89    private final DisplayInfo mDisplayInfo = new DisplayInfo();
90    private final Display mDisplay;
91    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
92
93    Rect mBaseDisplayRect = new Rect();
94    private Rect mContentRect = new Rect();
95
96    // Accessed directly by all users.
97    boolean layoutNeeded;
98    int pendingLayoutChanges;
99    final boolean isDefaultDisplay;
100
101    /** Window tokens that are in the process of exiting, but still on screen for animations. */
102    final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
103
104    /** Array containing all TaskStacks on this display.  Array
105     * is stored in display order with the current bottom stack at 0. */
106    private final ArrayList<TaskStack> mStacks = new ArrayList<>();
107
108    /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
109     * (except a future lockscreen TaskStack) moves to the top. */
110    private TaskStack mHomeStack = null;
111
112    /** Detect user tapping outside of current focused task bounds .*/
113    TaskTapPointerEventListener mTapDetector;
114
115    /** Detect user tapping outside of current focused stack bounds .*/
116    private Region mTouchExcludeRegion = new Region();
117
118    /** Save allocating when calculating rects */
119    private final Rect mTmpRect = new Rect();
120    private final Rect mTmpRect2 = new Rect();
121    private final Region mTmpRegion = new Region();
122
123    /** For gathering Task objects in order. */
124    private final ArrayList<Task> mTmpTaskHistory = new ArrayList<Task>();
125
126    final WindowManagerService mService;
127
128    /** Remove this display when animation on it has completed. */
129    boolean mDeferredRemoval;
130
131    final DockedStackDividerController mDividerControllerLocked;
132
133    final DimLayerController mDimLayerController;
134
135    final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
136
137    /** Used when rebuilding window list to keep track of windows that have been removed. */
138    private WindowState[] mRebuildTmp = new WindowState[20];
139
140    /**
141     * @param display May not be null.
142     * @param service You know.
143     */
144    DisplayContent(Display display, WindowManagerService service) {
145        mDisplay = display;
146        mDisplayId = display.getDisplayId();
147        display.getDisplayInfo(mDisplayInfo);
148        display.getMetrics(mDisplayMetrics);
149        isDefaultDisplay = mDisplayId == Display.DEFAULT_DISPLAY;
150        mService = service;
151        initializeDisplayBaseInfo();
152        mDividerControllerLocked = new DockedStackDividerController(service, this);
153        mDimLayerController = new DimLayerController(this);
154    }
155
156    int getDisplayId() {
157        return mDisplayId;
158    }
159
160    WindowList getWindowList() {
161        return mWindows;
162    }
163
164    Display getDisplay() {
165        return mDisplay;
166    }
167
168    DisplayInfo getDisplayInfo() {
169        return mDisplayInfo;
170    }
171
172    DisplayMetrics getDisplayMetrics() {
173        return mDisplayMetrics;
174    }
175
176    DockedStackDividerController getDockedDividerController() {
177        return mDividerControllerLocked;
178    }
179
180    /**
181     * Returns true if the specified UID has access to this display.
182     */
183    public boolean hasAccess(int uid) {
184        return mDisplay.hasAccess(uid);
185    }
186
187    public boolean isPrivate() {
188        return (mDisplay.getFlags() & Display.FLAG_PRIVATE) != 0;
189    }
190
191    ArrayList<TaskStack> getStacks() {
192        return mStacks;
193    }
194
195    /**
196     * Retrieve the tasks on this display in stack order from the bottommost TaskStack up.
197     * @return All the Tasks, in order, on this display.
198     */
199    ArrayList<Task> getTasks() {
200        mTmpTaskHistory.clear();
201        final int numStacks = mStacks.size();
202        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
203            mTmpTaskHistory.addAll(mStacks.get(stackNdx).getTasks());
204        }
205        return mTmpTaskHistory;
206    }
207
208    TaskStack getHomeStack() {
209        if (mHomeStack == null && mDisplayId == Display.DEFAULT_DISPLAY) {
210            Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
211        }
212        return mHomeStack;
213    }
214
215    TaskStack getStackById(int stackId) {
216        for (int i = mStacks.size() - 1; i >= 0; --i) {
217            final TaskStack stack = mStacks.get(i);
218            if (stack.mStackId == stackId) {
219                return stack;
220            }
221        }
222        return null;
223    }
224
225    void onAppTransitionDone() {
226        for (int i = mStacks.size() - 1; i >= 0; --i) {
227            final TaskStack stack = mStacks.get(i);
228            stack.onAppTransitionDone();
229        }
230
231        rebuildAppWindowList();
232    }
233
234    int getOrientation() {
235        // TODO: Most of the logic here can be removed once this class is converted to use
236        // WindowContainer which has an abstract implementation of getOrientation that
237        // should cover this.
238        if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
239                || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
240            // Apps and their containers are not allowed to specify an orientation while the docked
241            // or freeform stack is visible...except for the home stack/task if the docked stack is
242            // minimized and it actually set something.
243            if (mHomeStack.isVisible() && mDividerControllerLocked.isMinimizedDock()) {
244                final int orientation = mHomeStack.getOrientation();
245                if (orientation != SCREEN_ORIENTATION_UNSET) {
246                    return orientation;
247                }
248            }
249            return SCREEN_ORIENTATION_UNSPECIFIED;
250        }
251
252        for (int i = mStacks.size() - 1; i >= 0; --i) {
253            final TaskStack stack = mStacks.get(i);
254            if (!stack.isVisible()) {
255                continue;
256            }
257
258            final int orientation = stack.getOrientation();
259
260            if (orientation == SCREEN_ORIENTATION_BEHIND) {
261                continue;
262            }
263
264            if (orientation != SCREEN_ORIENTATION_UNSET) {
265                if (stack.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
266                    return orientation;
267                }
268            }
269        }
270
271        if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
272                "No app is requesting an orientation, return " + mService.mLastOrientation);
273        // The next app has not been requested to be visible, so we keep the current orientation
274        // to prevent freezing/unfreezing the display too early.
275        return mService.mLastOrientation;
276    }
277
278    void updateDisplayInfo() {
279        mDisplay.getDisplayInfo(mDisplayInfo);
280        mDisplay.getMetrics(mDisplayMetrics);
281        for (int i = mStacks.size() - 1; i >= 0; --i) {
282            mStacks.get(i).updateDisplayInfo(null);
283        }
284    }
285
286    void initializeDisplayBaseInfo() {
287        final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
288        if (displayManagerInternal != null) {
289            // Bootstrap the default logical display from the display manager.
290            final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
291            if (newDisplayInfo != null) {
292                mDisplayInfo.copyFrom(newDisplayInfo);
293            }
294        }
295
296        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
297        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
298        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
299        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
300    }
301
302    void getLogicalDisplayRect(Rect out) {
303        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
304        final int orientation = mDisplayInfo.rotation;
305        boolean rotated = (orientation == Surface.ROTATION_90
306                || orientation == Surface.ROTATION_270);
307        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
308        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
309        int width = mDisplayInfo.logicalWidth;
310        int left = (physWidth - width) / 2;
311        int height = mDisplayInfo.logicalHeight;
312        int top = (physHeight - height) / 2;
313        out.set(left, top, left + width, top + height);
314    }
315
316    void getContentRect(Rect out) {
317        out.set(mContentRect);
318    }
319
320    /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */
321    void attachStack(TaskStack stack, boolean onTop) {
322        if (stack.mStackId == HOME_STACK_ID) {
323            if (mHomeStack != null) {
324                throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
325            }
326            mHomeStack = stack;
327        }
328        if (onTop) {
329            mStacks.add(stack);
330        } else {
331            mStacks.add(0, stack);
332        }
333        layoutNeeded = true;
334    }
335
336    void moveStack(TaskStack stack, boolean toTop) {
337        if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
338            // This stack is always-on-top silly...
339            Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
340            return;
341        }
342
343        if (!mStacks.remove(stack)) {
344            Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
345        }
346
347        int addIndex = toTop ? mStacks.size() : 0;
348
349        if (toTop
350                && mService.isStackVisibleLocked(PINNED_STACK_ID)
351                && stack.mStackId != PINNED_STACK_ID) {
352            // The pinned stack is always the top most stack (always-on-top) when it is visible.
353            // So, stack is moved just below the pinned stack.
354            addIndex--;
355            TaskStack topStack = mStacks.get(addIndex);
356            if (topStack.mStackId != PINNED_STACK_ID) {
357                throw new IllegalStateException("Pinned stack isn't top stack??? " + mStacks);
358            }
359        }
360        mStacks.add(addIndex, stack);
361    }
362
363    void detachStack(TaskStack stack) {
364        mDimLayerController.removeDimLayerUser(stack);
365        mStacks.remove(stack);
366    }
367
368    /**
369     * Propagate the new bounds to all child stacks.
370     * @param contentRect The bounds to apply at the top level.
371     */
372    void resize(Rect contentRect) {
373        mContentRect.set(contentRect);
374    }
375
376    int taskIdFromPoint(int x, int y) {
377        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
378            TaskStack stack = mStacks.get(stackNdx);
379            stack.getBounds(mTmpRect);
380            if (!mTmpRect.contains(x, y) || stack.isAdjustedForMinimizedDockedStack()) {
381                continue;
382            }
383            final ArrayList<Task> tasks = stack.getTasks();
384            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
385                final Task task = tasks.get(taskNdx);
386                final WindowState win = task.getTopVisibleAppMainWindow();
387                if (win == null) {
388                    continue;
389                }
390                // We need to use the task's dim bounds (which is derived from the visible
391                // bounds of its apps windows) for any touch-related tests. Can't use
392                // the task's original bounds because it might be adjusted to fit the
393                // content frame. For example, the presence of the IME adjusting the
394                // windows frames when the app window is the IME target.
395                task.getDimBounds(mTmpRect);
396                if (mTmpRect.contains(x, y)) {
397                    return task.mTaskId;
398                }
399            }
400        }
401        return -1;
402    }
403
404    /**
405     * Find the task whose outside touch area (for resizing) (x, y) falls within.
406     * Returns null if the touch doesn't fall into a resizing area.
407     */
408    Task findTaskForResizePoint(int x, int y) {
409        final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
410        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
411            TaskStack stack = mStacks.get(stackNdx);
412            if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
413                break;
414            }
415            final ArrayList<Task> tasks = stack.getTasks();
416            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
417                final Task task = tasks.get(taskNdx);
418                if (task.isFullscreen()) {
419                    return null;
420                }
421
422                // We need to use the task's dim bounds (which is derived from the visible
423                // bounds of its apps windows) for any touch-related tests. Can't use
424                // the task's original bounds because it might be adjusted to fit the
425                // content frame. One example is when the task is put to top-left quadrant,
426                // the actual visible area would not start at (0,0) after it's adjusted
427                // for the status bar.
428                task.getDimBounds(mTmpRect);
429                mTmpRect.inset(-delta, -delta);
430                if (mTmpRect.contains(x, y)) {
431                    mTmpRect.inset(delta, delta);
432                    if (!mTmpRect.contains(x, y)) {
433                        return task;
434                    }
435                    // User touched inside the task. No need to look further,
436                    // focus transfer will be handled in ACTION_UP.
437                    return null;
438                }
439            }
440        }
441        return null;
442    }
443
444    void setTouchExcludeRegion(Task focusedTask) {
445        mTouchExcludeRegion.set(mBaseDisplayRect);
446        final int delta = mService.dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
447        boolean addBackFocusedTask = false;
448        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
449            TaskStack stack = mStacks.get(stackNdx);
450            final ArrayList<Task> tasks = stack.getTasks();
451            for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
452                final Task task = tasks.get(taskNdx);
453                AppWindowToken token = task.getTopVisibleAppToken();
454                if (token == null || !token.isVisible()) {
455                    continue;
456                }
457
458                /**
459                 * Exclusion region is the region that TapDetector doesn't care about.
460                 * Here we want to remove all non-focused tasks from the exclusion region.
461                 * We also remove the outside touch area for resizing for all freeform
462                 * tasks (including the focused).
463                 *
464                 * We save the focused task region once we find it, and add it back at the end.
465                 */
466
467                task.getDimBounds(mTmpRect);
468
469                if (task == focusedTask) {
470                    addBackFocusedTask = true;
471                    mTmpRect2.set(mTmpRect);
472                }
473
474                final boolean isFreeformed = task.inFreeformWorkspace();
475                if (task != focusedTask || isFreeformed) {
476                    if (isFreeformed) {
477                        // If the task is freeformed, enlarge the area to account for outside
478                        // touch area for resize.
479                        mTmpRect.inset(-delta, -delta);
480                        // Intersect with display content rect. If we have system decor (status bar/
481                        // navigation bar), we want to exclude that from the tap detection.
482                        // Otherwise, if the app is partially placed under some system button (eg.
483                        // Recents, Home), pressing that button would cause a full series of
484                        // unwanted transfer focus/resume/pause, before we could go home.
485                        mTmpRect.intersect(mContentRect);
486                    }
487                    mTouchExcludeRegion.op(mTmpRect, Region.Op.DIFFERENCE);
488                }
489            }
490        }
491        // If we removed the focused task above, add it back and only leave its
492        // outside touch area in the exclusion. TapDectector is not interested in
493        // any touch inside the focused task itself.
494        if (addBackFocusedTask) {
495            mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
496        }
497        final WindowState inputMethod = mService.mInputMethodWindow;
498        if (inputMethod != null && inputMethod.isVisibleLw()) {
499            // If the input method is visible and the user is typing, we don't want these touch
500            // events to be intercepted and used to change focus. This would likely cause a
501            // disappearance of the input method.
502            inputMethod.getTouchableRegion(mTmpRegion);
503            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
504        }
505        for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
506            WindowState win = mTapExcludedWindows.get(i);
507            win.getTouchableRegion(mTmpRegion);
508            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
509        }
510        if (getDockedStackVisibleForUserLocked() != null) {
511            mDividerControllerLocked.getTouchRegion(mTmpRect);
512            mTmpRegion.set(mTmpRect);
513            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
514        }
515        if (mTapDetector != null) {
516            mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
517        }
518    }
519
520    void switchUserStacks() {
521        final WindowList windows = getWindowList();
522        for (int i = 0; i < windows.size(); i++) {
523            final WindowState win = windows.get(i);
524            if (win.isHiddenFromUserLocked()) {
525                if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
526                        + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
527                win.hideLw(false);
528            }
529        }
530
531        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
532            mStacks.get(stackNdx).switchUser();
533        }
534
535        rebuildAppWindowList();
536    }
537
538    void resetAnimationBackgroundAnimator() {
539        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
540            mStacks.get(stackNdx).resetAnimationBackgroundAnimator();
541        }
542    }
543
544    boolean animateDimLayers() {
545        return mDimLayerController.animateDimLayers();
546    }
547
548    void resetDimming() {
549        mDimLayerController.resetDimming();
550    }
551
552    boolean isDimming() {
553        return mDimLayerController.isDimming();
554    }
555
556    void stopDimmingIfNeeded() {
557        mDimLayerController.stopDimmingIfNeeded();
558    }
559
560    void close() {
561        mDimLayerController.close();
562        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
563            mStacks.get(stackNdx).close();
564        }
565    }
566
567    boolean isAnimating() {
568        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
569            final TaskStack stack = mStacks.get(stackNdx);
570            if (stack.isAnimating()) {
571                return true;
572            }
573        }
574        return false;
575    }
576
577    void onCompleteDeferredRemoval() {
578        boolean animating = false;
579        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
580            final TaskStack stack = mStacks.get(stackNdx);
581            if (stack.isAnimating()) {
582                animating = true;
583            } else {
584                if (stack.mDeferDetach) {
585                    mService.detachStackLocked(this, stack);
586                }
587                final ArrayList<Task> tasks = stack.getTasks();
588                for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
589                    final Task task = tasks.get(taskNdx);
590                    AppTokenList tokens = task.mAppTokens;
591                    for (int tokenNdx = tokens.size() - 1; tokenNdx >= 0; --tokenNdx) {
592                        AppWindowToken wtoken = tokens.get(tokenNdx);
593                        if (wtoken.mIsExiting) {
594                            wtoken.removeIfPossible();
595                        }
596                    }
597                }
598            }
599        }
600        if (!animating && mDeferredRemoval) {
601            mService.onDisplayRemoved(mDisplayId);
602        }
603    }
604
605    void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
606        final int rotationDelta = DisplayContent.deltaRotation(oldRotation, newRotation);
607        getLogicalDisplayRect(mTmpRect);
608        switch (rotationDelta) {
609            case Surface.ROTATION_0:
610                mTmpRect2.set(bounds);
611                break;
612            case Surface.ROTATION_90:
613                mTmpRect2.top = mTmpRect.bottom - bounds.right;
614                mTmpRect2.left = bounds.top;
615                mTmpRect2.right = mTmpRect2.left + bounds.height();
616                mTmpRect2.bottom = mTmpRect2.top + bounds.width();
617                break;
618            case Surface.ROTATION_180:
619                mTmpRect2.top = mTmpRect.bottom - bounds.bottom;
620                mTmpRect2.left = mTmpRect.right - bounds.right;
621                mTmpRect2.right = mTmpRect2.left + bounds.width();
622                mTmpRect2.bottom = mTmpRect2.top + bounds.height();
623                break;
624            case Surface.ROTATION_270:
625                mTmpRect2.top = bounds.left;
626                mTmpRect2.left = mTmpRect.right - bounds.bottom;
627                mTmpRect2.right = mTmpRect2.left + bounds.height();
628                mTmpRect2.bottom = mTmpRect2.top + bounds.width();
629                break;
630        }
631        bounds.set(mTmpRect2);
632    }
633
634    static int deltaRotation(int oldRotation, int newRotation) {
635        int delta = newRotation - oldRotation;
636        if (delta < 0) delta += 4;
637        return delta;
638    }
639
640    public void dump(String prefix, PrintWriter pw) {
641        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
642        final String subPrefix = "  " + prefix;
643        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
644            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
645            pw.print("dpi");
646            if (mInitialDisplayWidth != mBaseDisplayWidth
647                    || mInitialDisplayHeight != mBaseDisplayHeight
648                    || mInitialDisplayDensity != mBaseDisplayDensity) {
649                pw.print(" base=");
650                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
651                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
652            }
653            if (mDisplayScalingDisabled) {
654                pw.println(" noscale");
655            }
656            pw.print(" cur=");
657            pw.print(mDisplayInfo.logicalWidth);
658            pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
659            pw.print(" app=");
660            pw.print(mDisplayInfo.appWidth);
661            pw.print("x"); pw.print(mDisplayInfo.appHeight);
662            pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
663            pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
664            pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
665            pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
666            pw.print(subPrefix); pw.print("deferred="); pw.print(mDeferredRemoval);
667                pw.print(" layoutNeeded="); pw.println(layoutNeeded);
668
669        pw.println();
670        pw.println("  Application tokens in top down Z order:");
671        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
672            final TaskStack stack = mStacks.get(stackNdx);
673            stack.dump(prefix + "  ", pw);
674        }
675
676        pw.println();
677        if (!mExitingTokens.isEmpty()) {
678            pw.println();
679            pw.println("  Exiting tokens:");
680            for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
681                WindowToken token = mExitingTokens.get(i);
682                pw.print("  Exiting #"); pw.print(i);
683                pw.print(' '); pw.print(token);
684                pw.println(':');
685                token.dump(pw, "    ");
686            }
687        }
688        pw.println();
689        mDimLayerController.dump(prefix + "  ", pw);
690        pw.println();
691        mDividerControllerLocked.dump(prefix + "  ", pw);
692    }
693
694    @Override
695    public String toString() {
696        return getName() + " stacks=" + mStacks;
697    }
698
699    String getName() {
700        return "Display " + mDisplayId + " info=" + mDisplayInfo;
701    }
702
703    /**
704     * @return The docked stack, but only if it is visible, and {@code null} otherwise.
705     */
706    TaskStack getDockedStackLocked() {
707        final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
708        return (stack != null && stack.isVisible()) ? stack : null;
709    }
710
711    /**
712     * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
713     * visible, as long as it's not hidden because the current user doesn't have any tasks there.
714     */
715    TaskStack getDockedStackVisibleForUserLocked() {
716        final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
717        return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
718    }
719
720    /** Find the visible, touch-deliverable window under the given point */
721    WindowState getTouchableWinAtPointLocked(float xf, float yf) {
722        WindowState touchedWin = null;
723        final int x = (int) xf;
724        final int y = (int) yf;
725
726        for (int i = mWindows.size() - 1; i >= 0; i--) {
727            WindowState window = mWindows.get(i);
728            final int flags = window.mAttrs.flags;
729            if (!window.isVisibleLw()) {
730                continue;
731            }
732            if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
733                continue;
734            }
735
736            window.getVisibleBounds(mTmpRect);
737            if (!mTmpRect.contains(x, y)) {
738                continue;
739            }
740
741            window.getTouchableRegion(mTmpRegion);
742
743            final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
744            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
745                touchedWin = window;
746                break;
747            }
748        }
749
750        return touchedWin;
751    }
752
753    /**
754     * See {@link WindowManagerService#overridePlayingAppAnimationsLw}.
755     */
756    void overridePlayingAppAnimationsLw(Animation a) {
757        for (int i = mStacks.size() - 1; i >= 0; i--) {
758            mStacks.get(i).overridePlayingAppAnimations(a);
759        }
760    }
761
762    boolean canAddToastWindowForUid(int uid) {
763        // We allow one toast window per UID being shown at a time.
764        WindowList windows = getWindowList();
765        final int windowCount = windows.size();
766        for (int i = 0; i < windowCount; i++) {
767            WindowState window = windows.get(i);
768            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
769                    && !window.mPermanentlyHidden && !window.mAnimatingExit) {
770                return false;
771            }
772        }
773        return true;
774    }
775
776    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus,
777                                                   WindowState newFocus) {
778        if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
779            return;
780        }
781        final int lostFocusUid = oldFocus.mOwnerUid;
782        WindowList windows = getWindowList();
783        final int windowCount = windows.size();
784        for (int i = 0; i < windowCount; i++) {
785            WindowState window = windows.get(i);
786            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
787                if (!mService.mH.hasMessages(WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window)) {
788                    mService.mH.sendMessageDelayed(
789                            mService.mH.obtainMessage(
790                                    WindowManagerService.H.WINDOW_HIDE_TIMEOUT, window),
791                            window.mAttrs.hideTimeoutMilliseconds);
792                }
793            }
794        }
795    }
796
797    WindowState findFocusedWindow() {
798        final AppWindowToken focusedApp = mService.mFocusedApp;
799
800        for (int i = mWindows.size() - 1; i >= 0; i--) {
801            final WindowState win = mWindows.get(i);
802
803            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
804                    + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
805
806            if (!win.canReceiveKeys()) {
807                continue;
808            }
809
810            final AppWindowToken wtoken = win.mAppToken;
811
812            // If this window's application has been removed, just skip it.
813            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
814                if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
815                        + (wtoken.removed ? "removed" : "sendingToBottom"));
816                continue;
817            }
818
819            if (focusedApp == null) {
820                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
821                        + " using new focus @ " + i + " = " + win);
822                return win;
823            }
824
825            if (!focusedApp.windowsAreFocusable()) {
826                // Current focused app windows aren't focusable...
827                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
828                        + " focusable using new focus @ " + i + " = " + win);
829                return win;
830            }
831
832            // Descend through all of the app tokens and find the first that either matches
833            // win.mAppToken (return win) or mFocusedApp (return null).
834            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
835                final TaskStack focusedAppStack = focusedApp.mTask.mStack;
836                final TaskStack appStack = wtoken.mTask.mStack;
837
838                // TODO: Use WindowContainer.compareTo() once everything is using WindowContainer
839                if ((focusedAppStack == appStack
840                        && appStack.isFirstGreaterThanSecond(focusedApp, wtoken))
841                        || mStacks.indexOf(focusedAppStack) > mStacks.indexOf(appStack)) {
842                    // App stack below focused app stack. No focus for you!!!
843                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
844                            "findFocusedWindow: Reached focused app=" + focusedApp);
845                    return null;
846                }
847            }
848
849            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
850                    + i + " = " + win);
851            return win;
852        }
853
854        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
855        return null;
856    }
857
858    int addAppWindowToWindowList(final WindowState win) {
859        final IWindow client = win.mClient;
860
861        WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
862        if (!tokenWindowList.isEmpty()) {
863            return addAppWindowExisting(win, tokenWindowList);
864        }
865
866        // No windows from this token on this display
867        if (mService.localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
868                + client.asBinder() + " (token=" + this + ")");
869
870        final WindowToken wToken = win.mToken;
871
872        // Figure out where the window should go, based on the order of applications.
873        final GetWindowOnDisplaySearchResults result = new GetWindowOnDisplaySearchResults();
874        for (int i = mStacks.size() - 1; i >= 0; --i) {
875            final TaskStack stack = mStacks.get(i);
876            stack.getWindowOnDisplayBeforeToken(this, wToken, result);
877            if (result.reachedToken) {
878                // We have reach the token we are interested in. End search.
879                break;
880            }
881        }
882
883        WindowState pos = result.foundWindow;
884
885        // We now know the index into the apps. If we found an app window above, that gives us the
886        // position; else we need to look some more.
887        if (pos != null) {
888            // Move behind any windows attached to this one.
889            final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
890            if (atoken != null) {
891                tokenWindowList = getTokenWindowsOnDisplay(atoken);
892                final int NC = tokenWindowList.size();
893                if (NC > 0) {
894                    WindowState bottom = tokenWindowList.get(0);
895                    if (bottom.mSubLayer < 0) {
896                        pos = bottom;
897                    }
898                }
899            }
900            addWindowToListBefore(win, pos);
901            return 0;
902        }
903
904        // Continue looking down until we find the first token that has windows on this display.
905        result.reset();
906        for (int i = mStacks.size() - 1; i >= 0; --i) {
907            final TaskStack stack = mStacks.get(i);
908            stack.getWindowOnDisplayAfterToken(this, wToken, result);
909            if (result.foundWindow != null) {
910                // We have found a window after the token. End search.
911                break;
912            }
913        }
914
915        pos = result.foundWindow;
916
917        if (pos != null) {
918            // Move in front of any windows attached to this one.
919            final WindowToken atoken = mService.mTokenMap.get(pos.mClient.asBinder());
920            if (atoken != null) {
921                final WindowState top = atoken.getTopWindow();
922                if (top != null && top.mSubLayer >= 0) {
923                    pos = top;
924                }
925            }
926            addWindowToListAfter(win, pos);
927            return 0;
928        }
929
930        // Just search for the start of this layer.
931        final int myLayer = win.mBaseLayer;
932        int i;
933        for (i = mWindows.size() - 1; i >= 0; --i) {
934            final WindowState w = mWindows.get(i);
935            // Dock divider shares the base layer with application windows, but we want to always
936            // keep it above the application windows. The sharing of the base layer is intended
937            // for window animations, which need to be above the dock divider for the duration
938            // of the animation.
939            if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
940                break;
941            }
942        }
943        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
944                "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
945                + mWindows.size());
946        mWindows.add(i + 1, win);
947        mService.mWindowsChanged = true;
948        return 0;
949    }
950
951    /** Adds this non-app window to the window list. */
952    void addNonAppWindowToWindowList(WindowState win) {
953        // Figure out where window should go, based on layer.
954        int i;
955        for (i = mWindows.size() - 1; i >= 0; i--) {
956            final WindowState otherWin = mWindows.get(i);
957            if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
958                // Wallpaper wanders through the window list, for example to position itself
959                // directly behind keyguard. Because of this it will break the ordering based on
960                // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
961                // we don't want the new window to appear above them. An example of this is adding
962                // of the docked stack divider. Consider a scenario with the following ordering (top
963                // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
964                // to land below the assist preview, so the dock divider must ignore the wallpaper,
965                // with which it shares the base layer.
966                break;
967            }
968        }
969
970        i++;
971        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
972                "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
973        mWindows.add(i, win);
974        mService.mWindowsChanged = true;
975    }
976
977    void addChildWindowToWindowList(WindowState win) {
978        final WindowState parentWindow = win.getParentWindow();
979
980        WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
981
982        // Figure out this window's ordering relative to the parent window.
983        final int wCount = windowsOnSameDisplay.size();
984        final int sublayer = win.mSubLayer;
985        int largestSublayer = Integer.MIN_VALUE;
986        WindowState windowWithLargestSublayer = null;
987        int i;
988        for (i = 0; i < wCount; i++) {
989            WindowState w = windowsOnSameDisplay.get(i);
990            final int wSublayer = w.mSubLayer;
991            if (wSublayer >= largestSublayer) {
992                largestSublayer = wSublayer;
993                windowWithLargestSublayer = w;
994            }
995            if (sublayer < 0) {
996                // For negative sublayers, we go below all windows in the same sublayer.
997                if (wSublayer >= sublayer) {
998                    addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
999                    break;
1000                }
1001            } else {
1002                // For positive sublayers, we go above all windows in the same sublayer.
1003                if (wSublayer > sublayer) {
1004                    addWindowToListBefore(win, w);
1005                    break;
1006                }
1007            }
1008        }
1009        if (i >= wCount) {
1010            if (sublayer < 0) {
1011                addWindowToListBefore(win, parentWindow);
1012            } else {
1013                addWindowToListAfter(win,
1014                        largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
1015            }
1016        }
1017    }
1018
1019    /**
1020     * Z-orders the display window list so that:
1021     * <ul>
1022     * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
1023     *      window.
1024     * <li>Exiting application windows are at the bottom, but above the wallpaper window.
1025     * <li>All other application windows are above the exiting application windows and ordered based
1026     *      on the ordering of their stacks and tasks on the display.
1027     * <li>Non-application windows are at the very top.
1028     * </ul>
1029     * <p>
1030     * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
1031     *       surface layering is done in {@link WindowLayersController}.
1032     */
1033    void rebuildAppWindowList() {
1034        int count = mWindows.size();
1035        int i;
1036        int lastBelow = -1;
1037        int numRemoved = 0;
1038
1039        if (mRebuildTmp.length < count) {
1040            mRebuildTmp = new WindowState[count + 10];
1041        }
1042
1043        // First remove all existing app windows.
1044        i = 0;
1045        while (i < count) {
1046            final WindowState w = mWindows.get(i);
1047            if (w.mAppToken != null) {
1048                final WindowState win = mWindows.remove(i);
1049                win.mRebuilding = true;
1050                mRebuildTmp[numRemoved] = win;
1051                mService.mWindowsChanged = true;
1052                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
1053                count--;
1054                numRemoved++;
1055                continue;
1056            } else if (lastBelow == i-1) {
1057                if (w.mAttrs.type == TYPE_WALLPAPER) {
1058                    lastBelow = i;
1059                }
1060            }
1061            i++;
1062        }
1063
1064        // Keep whatever windows were below the app windows still below, by skipping them.
1065        lastBelow++;
1066        i = lastBelow;
1067
1068        // First add all of the exiting app tokens...  these are no longer in the main app list,
1069        // but still have windows shown. We put them in the back because now that the animation is
1070        // over we no longer will care about them.
1071        final int numStacks = mStacks.size();
1072        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1073            AppTokenList exitingAppTokens = mStacks.get(stackNdx).mExitingAppTokens;
1074            int NT = exitingAppTokens.size();
1075            for (int j = 0; j < NT; j++) {
1076                i = exitingAppTokens.get(j).rebuildWindowList(this, i);
1077            }
1078        }
1079
1080        // And add in the still active app tokens in Z order.
1081        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1082            i = mStacks.get(stackNdx).rebuildWindowList(this, i);
1083        }
1084
1085        i -= lastBelow;
1086        if (i != numRemoved) {
1087            layoutNeeded = true;
1088            Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
1089                    + " windows but added " + i + " rebuildAppWindowListLocked() "
1090                    + " callers=" + Debug.getCallers(10));
1091            for (i = 0; i < numRemoved; i++) {
1092                WindowState ws = mRebuildTmp[i];
1093                if (ws.mRebuilding) {
1094                    StringWriter sw = new StringWriter();
1095                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
1096                    ws.dump(pw, "", true);
1097                    pw.flush();
1098                    Slog.w(TAG_WM, "This window was lost: " + ws);
1099                    Slog.w(TAG_WM, sw.toString());
1100                    ws.mWinAnimator.destroySurfaceLocked();
1101                }
1102            }
1103            Slog.w(TAG_WM, "Current app token list:");
1104            dumpChildrenNames();
1105            Slog.w(TAG_WM, "Final window list:");
1106            dumpWindows();
1107        }
1108        Arrays.fill(mRebuildTmp, null);
1109    }
1110
1111    /** Return the list of Windows on this display associated with the input token. */
1112    WindowList getTokenWindowsOnDisplay(WindowToken token) {
1113        final WindowList windowList = new WindowList();
1114        final int count = mWindows.size();
1115        for (int i = 0; i < count; i++) {
1116            final WindowState win = mWindows.get(i);
1117            if (win.mToken == token) {
1118                windowList.add(win);
1119            }
1120        }
1121        return windowList;
1122    }
1123
1124    private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
1125
1126        int tokenWindowsPos;
1127        // If this application has existing windows, we simply place the new window on top of
1128        // them... but keep the starting window on top.
1129        if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
1130            // Base windows go behind everything else.
1131            final WindowState lowestWindow = tokenWindowList.get(0);
1132            addWindowToListBefore(win, lowestWindow);
1133            tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow);
1134        } else {
1135            final AppWindowToken atoken = win.mAppToken;
1136            final int windowListPos = tokenWindowList.size();
1137            final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
1138            if (atoken != null && lastWindow == atoken.startingWindow) {
1139                addWindowToListBefore(win, lastWindow);
1140                tokenWindowsPos = win.mToken.getWindowIndex(lastWindow);
1141            } else {
1142                int newIdx = findIdxBasedOnAppTokens(win);
1143                // There is a window above this one associated with the same apptoken note that the
1144                // window could be a floating window that was created later or a window at the top
1145                // of the list of windows associated with this token.
1146                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1147                        "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
1148                                + mWindows.size());
1149                mWindows.add(newIdx + 1, win);
1150                if (newIdx < 0) {
1151                    // No window from token found on win's display.
1152                    tokenWindowsPos = 0;
1153                } else {
1154                    tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1;
1155                }
1156                mService.mWindowsChanged = true;
1157            }
1158        }
1159        return tokenWindowsPos;
1160    }
1161
1162    /** Places the first input window after the second input window in the window list. */
1163    private void addWindowToListAfter(WindowState first, WindowState second) {
1164        final int i = mWindows.indexOf(second);
1165        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1166                "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
1167                + " (after " + second + ")");
1168        mWindows.add(i + 1, first);
1169        mService.mWindowsChanged = true;
1170    }
1171
1172    /** Places the first input window before the second input window in the window list. */
1173    private void addWindowToListBefore(WindowState first, WindowState second) {
1174        int i = mWindows.indexOf(second);
1175        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1176                "Adding window " + this + " at " + i + " of " + mWindows.size()
1177                + " (before " + second + ")");
1178        if (i < 0) {
1179            Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
1180            i = 0;
1181        }
1182        mWindows.add(i, first);
1183        mService.mWindowsChanged = true;
1184    }
1185
1186    /**
1187     * This method finds out the index of a window that has the same app token as win. used for z
1188     * ordering the windows in mWindows
1189     */
1190    private int findIdxBasedOnAppTokens(WindowState win) {
1191        for(int j = mWindows.size() - 1; j >= 0; j--) {
1192            final WindowState wentry = mWindows.get(j);
1193            if(wentry.mAppToken == win.mAppToken) {
1194                return j;
1195            }
1196        }
1197        return -1;
1198    }
1199
1200    private void dumpChildrenNames() {
1201        StringWriter sw = new StringWriter();
1202        PrintWriter pw = new FastPrintWriter(sw, false, 1024);
1203        dumpChildrenNames(pw, "  ");
1204    }
1205
1206    private void dumpChildrenNames(PrintWriter pw, String prefix) {
1207        final String childPrefix = prefix + prefix;
1208        for (int j = mStacks.size() - 1; j >= 0; j--) {
1209            final TaskStack stack = mStacks.get(j);
1210            pw.println("#" + j + " " + getName());
1211            stack.dumpChildrenNames(pw, childPrefix);
1212        }
1213    }
1214
1215    private void dumpWindows() {
1216        final int numDisplays = mService.mDisplayContents.size();
1217        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
1218            final DisplayContent displayContent = mService.mDisplayContents.valueAt(displayNdx);
1219            Slog.v(TAG_WM, " Display #" + displayContent.getDisplayId());
1220            final WindowList windows = displayContent.getWindowList();
1221            for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
1222                Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
1223            }
1224        }
1225    }
1226
1227    static final class GetWindowOnDisplaySearchResults {
1228        boolean reachedToken;
1229        WindowState foundWindow;
1230
1231        void reset() {
1232            reachedToken = false;
1233            foundWindow = null;
1234        }
1235    }
1236}
1237