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