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