DisplayContent.java revision 3d0bfd9530bc51c52aec027eaf6d0dba918efc99
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.Display.DEFAULT_DISPLAY;
27import static android.view.Display.FLAG_PRIVATE;
28import static android.view.Surface.ROTATION_0;
29import static android.view.Surface.ROTATION_180;
30import static android.view.Surface.ROTATION_270;
31import static android.view.Surface.ROTATION_90;
32import static android.view.View.GONE;
33import static android.view.WindowManager.DOCKED_BOTTOM;
34import static android.view.WindowManager.DOCKED_INVALID;
35import static android.view.WindowManager.DOCKED_TOP;
36import static android.view.WindowManager.INPUT_CONSUMER_NAVIGATION;
37import static android.view.WindowManager.INPUT_CONSUMER_PIP;
38import static android.view.WindowManager.INPUT_CONSUMER_WALLPAPER;
39import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
40import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
41import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
42import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
43import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
44import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
45import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
46import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
47import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS;
48import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
49import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
50import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
51import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
52import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
53import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
54import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
55import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
56import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
57import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
58import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
59import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
60import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
61import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
62import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
63import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
64import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
65import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
66import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
77import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
78import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
79import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
80import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
81import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
82import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
83import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
84import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
85import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
86import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
87import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
88import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
89import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
90import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
91import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
92import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
93import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
94import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
95import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
96import static com.android.server.wm.WindowManagerService.dipToPixel;
97import static com.android.server.wm.WindowManagerService.localLOGV;
98import static com.android.server.wm.WindowManagerService.logSurface;
99import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
100import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
101import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
102import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
103
104import android.annotation.NonNull;
105import android.app.ActivityManager.StackId;
106import android.content.res.Configuration;
107import android.graphics.Bitmap;
108import android.graphics.Matrix;
109import android.graphics.Rect;
110import android.graphics.RectF;
111import android.graphics.Region;
112import android.graphics.Region.Op;
113import android.hardware.display.DisplayManagerInternal;
114import android.os.Debug;
115import android.os.Handler;
116import android.os.IBinder;
117import android.os.RemoteException;
118import android.os.SystemClock;
119import android.util.DisplayMetrics;
120import android.util.Slog;
121import android.view.Display;
122import android.view.DisplayInfo;
123import android.view.IWindow;
124import android.view.InputChannel;
125import android.view.Surface;
126import android.view.SurfaceControl;
127import android.view.WindowManagerPolicy;
128
129import com.android.internal.util.FastPrintWriter;
130import com.android.internal.util.ToBooleanFunction;
131import com.android.internal.view.IInputMethodClient;
132import com.android.server.input.InputWindowHandle;
133
134import java.io.FileDescriptor;
135import java.io.PrintWriter;
136import java.io.StringWriter;
137import java.util.ArrayList;
138import java.util.Arrays;
139import java.util.Comparator;
140import java.util.HashMap;
141import java.util.Iterator;
142import java.util.LinkedList;
143import java.util.List;
144
145/**
146 * Utility class for keeping track of the WindowStates and other pertinent contents of a
147 * particular Display.
148 *
149 * IMPORTANT: No method from this class should ever be used without holding
150 * WindowManagerService.mWindowMap.
151 */
152class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
153    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
154
155    /** Unique identifier of this stack. */
156    private final int mDisplayId;
157
158    /** The containers below are the only child containers the display can have. */
159    // Contains all window containers that are related to apps (Activities)
160    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
161    // Contains all non-app window containers that should be displayed above the app containers
162    // (e.g. Status bar)
163    private final NonAppWindowContainers mAboveAppWindowsContainers =
164            new NonAppWindowContainers("mAboveAppWindowsContainers");
165    // Contains all non-app window containers that should be displayed below the app containers
166    // (e.g. Wallpaper).
167    private final NonAppWindowContainers mBelowAppWindowsContainers =
168            new NonAppWindowContainers("mBelowAppWindowsContainers");
169    // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
170    // on the IME target. We mainly have this container grouping so we can keep track of all the IME
171    // window containers together and move them in-sync if/when needed.
172    private final NonAppWindowContainers mImeWindowsContainers =
173            new NonAppWindowContainers("mImeWindowsContainers");
174
175    // Z-ordered (bottom-most first) list of all Window objects.
176    private final WindowList mWindows = new WindowList();
177
178    // Mapping from a token IBinder to a WindowToken object on this display.
179    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
180
181    int mInitialDisplayWidth = 0;
182    int mInitialDisplayHeight = 0;
183    int mInitialDisplayDensity = 0;
184    int mBaseDisplayWidth = 0;
185    int mBaseDisplayHeight = 0;
186    int mBaseDisplayDensity = 0;
187    boolean mDisplayScalingDisabled;
188    private final DisplayInfo mDisplayInfo = new DisplayInfo();
189    private final Display mDisplay;
190    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
191
192    Rect mBaseDisplayRect = new Rect();
193    private Rect mContentRect = new Rect();
194
195    // Accessed directly by all users.
196    private boolean mLayoutNeeded;
197    int pendingLayoutChanges;
198    // TODO(multi-display): remove some of the usages.
199    final boolean isDefaultDisplay;
200
201    /** Window tokens that are in the process of exiting, but still on screen for animations. */
202    final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
203
204    /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
205     * (except a future lockscreen TaskStack) moves to the top. */
206    private TaskStack mHomeStack = null;
207
208    /** Detect user tapping outside of current focused task bounds .*/
209    TaskTapPointerEventListener mTapDetector;
210
211    /** Detect user tapping outside of current focused stack bounds .*/
212    private Region mTouchExcludeRegion = new Region();
213
214    /** Save allocating when calculating rects */
215    private final Rect mTmpRect = new Rect();
216    private final Rect mTmpRect2 = new Rect();
217    private final RectF mTmpRectF = new RectF();
218    private final Matrix mTmpMatrix = new Matrix();
219    private final Region mTmpRegion = new Region();
220
221    final WindowManagerService mService;
222
223    /** Remove this display when animation on it has completed. */
224    private boolean mDeferredRemoval;
225
226    final DockedStackDividerController mDividerControllerLocked;
227    final PinnedStackController mPinnedStackControllerLocked;
228
229    final DimLayerController mDimLayerController;
230
231    final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
232
233    /** Used when rebuilding window list to keep track of windows that have been removed. */
234    private WindowState[] mRebuildTmp = new WindowState[20];
235
236    /**
237     * Temporary list for comparison. Always clear this after use so we don't end up with
238     * orphaned windows references
239     */
240    private final ArrayList<WindowState> mTmpWindows = new ArrayList<>();
241
242    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
243
244    private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
245            new TaskForResizePointSearchResult();
246    private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
247            new GetWindowOnDisplaySearchResult();
248
249    // True if this display is in the process of being removed. Used to determine if the removal of
250    // the display's direct children should be allowed.
251    private boolean mRemovingDisplay = false;
252
253    private final WindowLayersController mLayersController;
254    final WallpaperController mWallpaperController;
255    int mInputMethodAnimLayerAdjustment;
256
257    /**
258     * @param display May not be null.
259     * @param service You know.
260     * @param layersController window layer controller used to assign layer to the windows on this
261     *                         display.
262     * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
263     *                            wallpaper windows in the window list.
264     */
265    DisplayContent(Display display, WindowManagerService service,
266            WindowLayersController layersController, WallpaperController wallpaperController) {
267        mDisplay = display;
268        mDisplayId = display.getDisplayId();
269        mLayersController = layersController;
270        mWallpaperController = wallpaperController;
271        display.getDisplayInfo(mDisplayInfo);
272        display.getMetrics(mDisplayMetrics);
273        isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
274        mService = service;
275        initializeDisplayBaseInfo();
276        mDividerControllerLocked = new DockedStackDividerController(service, this);
277        mPinnedStackControllerLocked = new PinnedStackController(service, this);
278        mDimLayerController = new DimLayerController(this);
279
280        // These are the only direct children we should ever have and they are permanent.
281        super.addChild(mBelowAppWindowsContainers, null);
282        super.addChild(mTaskStackContainers, null);
283        super.addChild(mAboveAppWindowsContainers, null);
284        super.addChild(mImeWindowsContainers, null);
285    }
286
287    int getDisplayId() {
288        return mDisplayId;
289    }
290
291    WindowToken getWindowToken(IBinder binder) {
292        return mTokenMap.get(binder);
293    }
294
295    AppWindowToken getAppWindowToken(IBinder binder) {
296        final WindowToken token = getWindowToken(binder);
297        if (token == null) {
298            return null;
299        }
300        return token.asAppWindowToken();
301    }
302
303    void addWindowToken(IBinder binder, WindowToken token) {
304        final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
305        if (dc != null) {
306            // We currently don't support adding a window token to the display if the display
307            // already has the binder mapped to another token. If there is a use case for supporting
308            // this moving forward we will either need to merge the WindowTokens some how or have
309            // the binder map to a list of window tokens.
310            throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
311                    + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
312        }
313        mTokenMap.put(binder, token);
314
315        if (token.asAppWindowToken() == null) {
316            // Add non-app token to container hierarchy on the display. App tokens are added through
317            // the parent container managing them (e.g. Tasks).
318            switch (token.windowType) {
319                case TYPE_WALLPAPER:
320                    mBelowAppWindowsContainers.addChild(token);
321                    break;
322                case TYPE_INPUT_METHOD:
323                case TYPE_INPUT_METHOD_DIALOG:
324                    mImeWindowsContainers.addChild(token);
325                    break;
326                default:
327                    mAboveAppWindowsContainers.addChild(token);
328                    break;
329            }
330        }
331    }
332
333    WindowToken removeWindowToken(IBinder binder) {
334        final WindowToken token = mTokenMap.remove(binder);
335        if (token != null && token.asAppWindowToken() == null) {
336            token.setExiting();
337        }
338        return token;
339    }
340
341    /** Changes the display the input window token is housed on to this one. */
342    void reParentWindowToken(WindowToken token) {
343        final DisplayContent prevDc = token.getDisplayContent();
344        if (prevDc == this) {
345            return;
346        }
347        if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null) {
348            switch (token.windowType) {
349                case TYPE_WALLPAPER:
350                    prevDc.mBelowAppWindowsContainers.removeChild(token);
351                    break;
352                case TYPE_INPUT_METHOD:
353                case TYPE_INPUT_METHOD_DIALOG:
354                    prevDc.mImeWindowsContainers.removeChild(token);
355                    break;
356                default:
357                    prevDc.mAboveAppWindowsContainers.removeChild(token);
358                    break;
359            }
360        }
361
362        addWindowToken(token.token, token);
363    }
364
365    void removeAppToken(IBinder binder) {
366        final WindowToken token = removeWindowToken(binder);
367        if (token == null) {
368            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
369            return;
370        }
371
372        final AppWindowToken appToken = token.asAppWindowToken();
373
374        if (appToken == null) {
375            Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
376            return;
377        }
378
379        appToken.onRemovedFromDisplay();
380    }
381
382    Display getDisplay() {
383        return mDisplay;
384    }
385
386    DisplayInfo getDisplayInfo() {
387        return mDisplayInfo;
388    }
389
390    DisplayMetrics getDisplayMetrics() {
391        return mDisplayMetrics;
392    }
393
394    DockedStackDividerController getDockedDividerController() {
395        return mDividerControllerLocked;
396    }
397
398    PinnedStackController getPinnedStackController() {
399        return mPinnedStackControllerLocked;
400    }
401
402    /**
403     * Returns true if the specified UID has access to this display.
404     */
405    boolean hasAccess(int uid) {
406        return mDisplay.hasAccess(uid);
407    }
408
409    boolean isPrivate() {
410        return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
411    }
412
413    TaskStack getHomeStack() {
414        if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
415            Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
416        }
417        return mHomeStack;
418    }
419
420    TaskStack getStackById(int stackId) {
421        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
422            final TaskStack stack = mTaskStackContainers.get(i);
423            if (stack.mStackId == stackId) {
424                return stack;
425            }
426        }
427        return null;
428    }
429
430    @Override
431    void onConfigurationChanged(Configuration newParentConfig) {
432        super.onConfigurationChanged(newParentConfig);
433
434        // The display size information is heavily dependent on the resources in the current
435        // configuration, so we need to reconfigure it every time the configuration changes.
436        // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
437        mService.reconfigureDisplayLocked(this);
438
439        getDockedDividerController().onConfigurationChanged();
440        getPinnedStackController().onConfigurationChanged();
441    }
442
443    /**
444     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
445     * bounds were updated.
446     */
447    void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
448        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
449            final TaskStack stack = mTaskStackContainers.get(i);
450            if (stack.updateBoundsAfterConfigChange()) {
451                changedStackList.add(stack.mStackId);
452            }
453        }
454    }
455
456    @Override
457    boolean fillsParent() {
458        return true;
459    }
460
461    @Override
462    boolean isVisible() {
463        return true;
464    }
465
466    @Override
467    void onAppTransitionDone() {
468        super.onAppTransitionDone();
469        rebuildAppWindowList();
470    }
471
472    @Override
473    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
474        // Special handling so we can process IME windows with #forAllImeWindows above their IME
475        // target, or here in order if there isn't an IME target.
476        if (traverseTopToBottom) {
477            for (int i = mChildren.size() - 1; i >= 0; --i) {
478                final DisplayChildWindowContainer child = mChildren.get(i);
479                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
480                    // In this case the Ime windows will be processed above their target so we skip
481                    // here.
482                    continue;
483                }
484                if (child.forAllWindows(callback, traverseTopToBottom)) {
485                    return true;
486                }
487            }
488        } else {
489            final int count = mChildren.size();
490            for (int i = 0; i < count; i++) {
491                final DisplayChildWindowContainer child = mChildren.get(i);
492                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
493                    // In this case the Ime windows will be processed above their target so we skip
494                    // here.
495                    continue;
496                }
497                if (child.forAllWindows(callback, traverseTopToBottom)) {
498                    return true;
499                }
500            }
501        }
502        return false;
503    }
504
505    boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
506        return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
507    }
508
509    @Override
510    int getOrientation() {
511        final WindowManagerPolicy policy = mService.mPolicy;
512
513        // TODO: All the logic before the last return statement in this method should really go in
514        // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based
515        // on non-app windows. But, we can not do that until the window list is always correct in
516        // terms of z-ordering based on layers.
517        if (mService.mDisplayFrozen) {
518            if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
519                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
520                        "Display is frozen, return " + mService.mLastWindowForcedOrientation);
521                // If the display is frozen, some activities may be in the middle of restarting, and
522                // thus have removed their old window. If the window has the flag to hide the lock
523                // screen, then the lock screen can re-appear and inflict its own orientation on us.
524                // Keep the orientation stable until this all settles down.
525                return mService.mLastWindowForcedOrientation;
526            } else if (policy.isKeyguardLocked()) {
527                // Use the last orientation the while the display is frozen with the keyguard
528                // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
529                // window. We don't want to check the show when locked window directly though as
530                // things aren't stable while the display is frozen, for example the window could be
531                // momentarily unavailable due to activity relaunch.
532                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
533                        + "return " + mService.mLastOrientation);
534                return mService.mLastOrientation;
535            }
536        } else {
537            for (int pos = mWindows.size() - 1; pos >= 0; --pos) {
538                final WindowState win = mWindows.get(pos);
539                if (win.mAppToken != null) {
540                    // We hit an application window. so the orientation will be determined by the
541                    // app window. No point in continuing further.
542                    break;
543                }
544                if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
545                    continue;
546                }
547                int req = win.mAttrs.screenOrientation;
548                if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
549                    continue;
550                }
551
552                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
553                if (policy.isKeyguardHostWindow(win.mAttrs)) {
554                    mService.mLastKeyguardForcedOrientation = req;
555                }
556                return (mService.mLastWindowForcedOrientation = req);
557            }
558            mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
559
560            if (policy.isKeyguardShowingAndNotOccluded()) {
561                return mService.mLastKeyguardForcedOrientation;
562            }
563        }
564
565        // Top system windows are not requesting an orientation. Start searching from apps.
566        return mTaskStackContainers.getOrientation();
567    }
568
569    void updateDisplayInfo() {
570        mDisplay.getDisplayInfo(mDisplayInfo);
571        mDisplay.getMetrics(mDisplayMetrics);
572        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
573            mTaskStackContainers.get(i).updateDisplayInfo(null);
574        }
575    }
576
577    void initializeDisplayBaseInfo() {
578        final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
579        if (displayManagerInternal != null) {
580            // Bootstrap the default logical display from the display manager.
581            final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
582            if (newDisplayInfo != null) {
583                mDisplayInfo.copyFrom(newDisplayInfo);
584            }
585        }
586
587        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
588        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
589        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
590        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
591    }
592
593    void getLogicalDisplayRect(Rect out) {
594        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
595        final int orientation = mDisplayInfo.rotation;
596        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
597        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
598        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
599        int width = mDisplayInfo.logicalWidth;
600        int left = (physWidth - width) / 2;
601        int height = mDisplayInfo.logicalHeight;
602        int top = (physHeight - height) / 2;
603        out.set(left, top, left + width, top + height);
604    }
605
606    private void getLogicalDisplayRect(Rect out, int orientation) {
607        getLogicalDisplayRect(out);
608
609        // Rotate the Rect if needed.
610        final int currentRotation = mDisplayInfo.rotation;
611        final int rotationDelta = deltaRotation(currentRotation, orientation);
612        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
613            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
614            mTmpRectF.set(out);
615            mTmpMatrix.mapRect(mTmpRectF);
616            mTmpRectF.round(out);
617        }
618    }
619
620    void getContentRect(Rect out) {
621        out.set(mContentRect);
622    }
623
624    /**
625     * Adds the stack to this display.
626     * @see WindowManagerService#addStackToDisplay(int, int, boolean)
627     */
628    Rect addStackToDisplay(int stackId, boolean onTop) {
629        boolean attachedToDisplay = false;
630        TaskStack stack = mService.mStackIdToStack.get(stackId);
631        if (stack == null) {
632            if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
633                    + mDisplayId);
634
635            stack = getStackById(stackId);
636            if (stack != null) {
637                // It's already attached to the display...clear mDeferRemoval and move stack to
638                // appropriate z-order on display as needed.
639                stack.mDeferRemoval = false;
640                moveStack(stack, onTop);
641                attachedToDisplay = true;
642            } else {
643                stack = new TaskStack(mService, stackId);
644            }
645
646            mService.mStackIdToStack.put(stackId, stack);
647            if (stackId == DOCKED_STACK_ID) {
648                mDividerControllerLocked.notifyDockedStackExistsChanged(true);
649            }
650        } else {
651            final DisplayContent currentDC = stack.getDisplayContent();
652            if (currentDC != null) {
653                throw new IllegalStateException("Trying to add stackId=" + stackId
654                        + "to displayId=" + mDisplayId + ", but it's already attached to displayId="
655                        + currentDC.getDisplayId());
656            }
657        }
658
659        if (!attachedToDisplay) {
660            mTaskStackContainers.addStackToDisplay(stack, onTop);
661        }
662
663        if (stack.getRawFullscreen()) {
664            return null;
665        }
666        final Rect bounds = new Rect();
667        stack.getRawBounds(bounds);
668        return bounds;
669    }
670
671    /** Removes the stack from the display and prepares for changing the parent. */
672    private void removeStackFromDisplay(TaskStack stack) {
673        mTaskStackContainers.removeStackFromDisplay(stack);
674    }
675
676    /** Moves the stack to this display and returns the updated bounds. */
677    Rect moveStackToDisplay(TaskStack stack) {
678        final DisplayContent currentDisplayContent = stack.getDisplayContent();
679        if (currentDisplayContent == null) {
680            throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
681                    + " which is not currently attached to any display");
682        }
683        if (stack.getDisplayContent().getDisplayId() == mDisplayId) {
684            throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
685                    + " to its current displayId=" + mDisplayId);
686        }
687
688        currentDisplayContent.removeStackFromDisplay(stack);
689        return addStackToDisplay(stack.mStackId, true /* onTop */);
690    }
691
692    void moveStack(TaskStack stack, boolean toTop) {
693        mTaskStackContainers.moveStack(stack, toTop);
694    }
695
696    @Override
697    protected void addChild(DisplayChildWindowContainer child,
698            Comparator<DisplayChildWindowContainer> comparator) {
699        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
700    }
701
702    @Override
703    protected void addChild(DisplayChildWindowContainer child, int index) {
704        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
705    }
706
707    @Override
708    protected void removeChild(DisplayChildWindowContainer child) {
709        // Only allow removal of direct children from this display if the display is in the process
710        // of been removed.
711        if (mRemovingDisplay) {
712            super.removeChild(child);
713            return;
714        }
715        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
716    }
717
718    int taskIdFromPoint(int x, int y) {
719        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
720            final TaskStack stack = mTaskStackContainers.get(stackNdx);
721            final int taskId = stack.taskIdFromPoint(x, y);
722            if (taskId != -1) {
723                return taskId;
724            }
725        }
726        return -1;
727    }
728
729    /**
730     * Find the task whose outside touch area (for resizing) (x, y) falls within.
731     * Returns null if the touch doesn't fall into a resizing area.
732     */
733    Task findTaskForResizePoint(int x, int y) {
734        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
735        mTmpTaskForResizePointSearchResult.reset();
736        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
737            final TaskStack stack = mTaskStackContainers.get(stackNdx);
738            if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
739                return null;
740            }
741
742            stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
743            if (mTmpTaskForResizePointSearchResult.searchDone) {
744                return mTmpTaskForResizePointSearchResult.taskForResize;
745            }
746        }
747        return null;
748    }
749
750    void setTouchExcludeRegion(Task focusedTask) {
751        mTouchExcludeRegion.set(mBaseDisplayRect);
752        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
753        mTmpRect2.setEmpty();
754        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
755            final TaskStack stack = mTaskStackContainers.get(stackNdx);
756            stack.setTouchExcludeRegion(
757                    focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
758        }
759        // If we removed the focused task above, add it back and only leave its
760        // outside touch area in the exclusion. TapDectector is not interested in
761        // any touch inside the focused task itself.
762        if (!mTmpRect2.isEmpty()) {
763            mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
764        }
765        final WindowState inputMethod = mService.mInputMethodWindow;
766        if (inputMethod != null && inputMethod.isVisibleLw()) {
767            // If the input method is visible and the user is typing, we don't want these touch
768            // events to be intercepted and used to change focus. This would likely cause a
769            // disappearance of the input method.
770            inputMethod.getTouchableRegion(mTmpRegion);
771            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
772        }
773        for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
774            WindowState win = mTapExcludedWindows.get(i);
775            win.getTouchableRegion(mTmpRegion);
776            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
777        }
778        // TODO(multi-display): Support docked stacks on secondary displays.
779        if (mDisplayId == DEFAULT_DISPLAY && getDockedStackLocked() != null) {
780            mDividerControllerLocked.getTouchRegion(mTmpRect);
781            mTmpRegion.set(mTmpRect);
782            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
783        }
784        if (mTapDetector != null) {
785            mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
786        }
787    }
788
789    void switchUser() {
790        final int count = mWindows.size();
791        for (int i = 0; i < count; i++) {
792            final WindowState win = mWindows.get(i);
793            if (win.isHiddenFromUserLocked()) {
794                if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
795                        + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
796                win.hideLw(false);
797            }
798        }
799
800        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
801            mTaskStackContainers.get(stackNdx).switchUser();
802        }
803
804        rebuildAppWindowList();
805    }
806
807    private void resetAnimationBackgroundAnimator() {
808        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
809            mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
810        }
811    }
812
813    boolean animateDimLayers() {
814        return mDimLayerController.animateDimLayers();
815    }
816
817    private void resetDimming() {
818        mDimLayerController.resetDimming();
819    }
820
821    boolean isDimming() {
822        return mDimLayerController.isDimming();
823    }
824
825    private void stopDimmingIfNeeded() {
826        mDimLayerController.stopDimmingIfNeeded();
827    }
828
829    @Override
830    void removeIfPossible() {
831        if (isAnimating()) {
832            mDeferredRemoval = true;
833            return;
834        }
835        removeImmediately();
836    }
837
838    @Override
839    void removeImmediately() {
840        mRemovingDisplay = true;
841        try {
842            super.removeImmediately();
843            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
844            mDimLayerController.close();
845            if (mDisplayId == DEFAULT_DISPLAY) {
846                mService.unregisterPointerEventListener(mTapDetector);
847                mService.unregisterPointerEventListener(mService.mMousePositionTracker);
848            }
849        } finally {
850            mRemovingDisplay = false;
851        }
852    }
853
854    /** Returns true if a removal action is still being deferred. */
855    @Override
856    boolean checkCompleteDeferredRemoval() {
857        final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
858
859        if (!stillDeferringRemoval && mDeferredRemoval) {
860            removeImmediately();
861            mService.onDisplayRemoved(mDisplayId);
862            return false;
863        }
864        return true;
865    }
866
867    boolean animateForIme(float interpolatedValue, float animationTarget,
868            float dividerAnimationTarget) {
869        boolean updated = false;
870
871        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
872            final TaskStack stack = mTaskStackContainers.get(i);
873            if (stack == null || !stack.isAdjustedForIme()) {
874                continue;
875            }
876
877            if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
878                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
879                updated = true;
880            } else {
881                mDividerControllerLocked.mLastAnimationProgress =
882                        mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
883                mDividerControllerLocked.mLastDividerProgress =
884                        mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
885                updated |= stack.updateAdjustForIme(
886                        mDividerControllerLocked.mLastAnimationProgress,
887                        mDividerControllerLocked.mLastDividerProgress,
888                        false /* force */);
889            }
890            if (interpolatedValue >= 1f) {
891                stack.endImeAdjustAnimation();
892            }
893        }
894
895        return updated;
896    }
897
898    boolean clearImeAdjustAnimation() {
899        boolean changed = false;
900        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
901            final TaskStack stack = mTaskStackContainers.get(i);
902            if (stack != null && stack.isAdjustedForIme()) {
903                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
904                changed  = true;
905            }
906        }
907        return changed;
908    }
909
910    void beginImeAdjustAnimation() {
911        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
912            final TaskStack stack = mTaskStackContainers.get(i);
913            if (stack.isVisible() && stack.isAdjustedForIme()) {
914                stack.beginImeAdjustAnimation();
915            }
916        }
917    }
918
919    void adjustForImeIfNeeded() {
920        final WindowState imeWin = mService.mInputMethodWindow;
921        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
922                && !mDividerControllerLocked.isImeHideRequested();
923        final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
924        final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
925        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
926                imeTargetStack.getDockSide() : DOCKED_INVALID;
927        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
928        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
929        final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
930        final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
931        final boolean imeHeightChanged = imeVisible &&
932                imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
933
934        // The divider could be adjusted for IME position, or be thinner than usual,
935        // or both. There are three possible cases:
936        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
937        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
938        // - If IME is not visible, divider is not moved and is normal width.
939
940        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
941            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
942                final TaskStack stack = mTaskStackContainers.get(i);
943                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
944                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
945                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
946                } else {
947                    stack.resetAdjustedForIme(false);
948                }
949            }
950            mDividerControllerLocked.setAdjustedForIme(
951                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
952        } else {
953            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
954                final TaskStack stack = mTaskStackContainers.get(i);
955                stack.resetAdjustedForIme(!dockVisible);
956            }
957            mDividerControllerLocked.setAdjustedForIme(
958                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
959        }
960        mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
961    }
962
963    void setInputMethodAnimLayerAdjustment(int adj) {
964        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
965        mInputMethodAnimLayerAdjustment = adj;
966        final WindowState imw = mService.mInputMethodWindow;
967        if (imw != null) {
968            imw.adjustAnimLayer(adj);
969        }
970        for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
971            final WindowState dialog = mService.mInputMethodDialogs.get(i);
972            // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
973            // but need to make sure we are not setting things twice for child windows that are
974            // already in the list.
975            dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
976            if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
977                    + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
978        }
979    }
980
981    /**
982     * If a window that has an animation specifying a colored background and the current wallpaper
983     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
984     * suddenly disappear.
985     */
986    int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
987        for (int i = mWindows.size() - 1; i >= 0; --i) {
988            final WindowState win = mWindows.get(i);
989            if (win.mIsWallpaper && win.isVisibleNow()) {
990                return win.mWinAnimator.mAnimLayer;
991            }
992        }
993        return winAnimator.mAnimLayer;
994    }
995
996    void prepareFreezingTaskBounds() {
997        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
998            final TaskStack stack = mTaskStackContainers.get(stackNdx);
999            stack.prepareFreezingTaskBounds();
1000        }
1001    }
1002
1003    void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
1004        getLogicalDisplayRect(mTmpRect, newRotation);
1005
1006        // Compute a transform matrix to undo the coordinate space transformation,
1007        // and present the window at the same physical position it previously occupied.
1008        final int deltaRotation = deltaRotation(newRotation, oldRotation);
1009        createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
1010
1011        mTmpRectF.set(bounds);
1012        mTmpMatrix.mapRect(mTmpRectF);
1013        mTmpRectF.round(bounds);
1014    }
1015
1016    static int deltaRotation(int oldRotation, int newRotation) {
1017        int delta = newRotation - oldRotation;
1018        if (delta < 0) delta += 4;
1019        return delta;
1020    }
1021
1022    private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
1023            Matrix outMatrix) {
1024        // For rotations without Z-ordering we don't need the target rectangle's position.
1025        createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
1026                displayHeight, outMatrix);
1027    }
1028
1029    static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
1030            float displayWidth, float displayHeight, Matrix outMatrix) {
1031        switch (rotation) {
1032            case ROTATION_0:
1033                outMatrix.reset();
1034                break;
1035            case ROTATION_270:
1036                outMatrix.setRotate(270, 0, 0);
1037                outMatrix.postTranslate(0, displayHeight);
1038                outMatrix.postTranslate(rectTop, 0);
1039                break;
1040            case ROTATION_180:
1041                outMatrix.reset();
1042                break;
1043            case ROTATION_90:
1044                outMatrix.setRotate(90, 0, 0);
1045                outMatrix.postTranslate(displayWidth, 0);
1046                outMatrix.postTranslate(-rectTop, rectLeft);
1047                break;
1048        }
1049    }
1050
1051    public void dump(String prefix, PrintWriter pw) {
1052        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
1053        final String subPrefix = "  " + prefix;
1054        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
1055            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
1056            pw.print("dpi");
1057            if (mInitialDisplayWidth != mBaseDisplayWidth
1058                    || mInitialDisplayHeight != mBaseDisplayHeight
1059                    || mInitialDisplayDensity != mBaseDisplayDensity) {
1060                pw.print(" base=");
1061                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
1062                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
1063            }
1064            if (mDisplayScalingDisabled) {
1065                pw.println(" noscale");
1066            }
1067            pw.print(" cur=");
1068            pw.print(mDisplayInfo.logicalWidth);
1069            pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
1070            pw.print(" app=");
1071            pw.print(mDisplayInfo.appWidth);
1072            pw.print("x"); pw.print(mDisplayInfo.appHeight);
1073            pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
1074            pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
1075            pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
1076            pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
1077            pw.println(subPrefix + "deferred=" + mDeferredRemoval
1078                    + " mLayoutNeeded=" + mLayoutNeeded);
1079
1080        pw.println();
1081        pw.println(prefix + "Application tokens in top down Z order:");
1082        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1083            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1084            stack.dump(prefix + "  ", pw);
1085        }
1086
1087        pw.println();
1088        if (!mExitingTokens.isEmpty()) {
1089            pw.println();
1090            pw.println("  Exiting tokens:");
1091            for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
1092                final WindowToken token = mExitingTokens.get(i);
1093                pw.print("  Exiting #"); pw.print(i);
1094                pw.print(' '); pw.print(token);
1095                pw.println(':');
1096                token.dump(pw, "    ");
1097            }
1098        }
1099        pw.println();
1100        mDimLayerController.dump(prefix, pw);
1101        pw.println();
1102        mDividerControllerLocked.dump(prefix, pw);
1103        pw.println();
1104        mPinnedStackControllerLocked.dump(prefix, pw);
1105
1106        if (mInputMethodAnimLayerAdjustment != 0) {
1107            pw.println(subPrefix
1108                    + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment);
1109        }
1110    }
1111
1112    @Override
1113    public String toString() {
1114        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
1115    }
1116
1117    String getName() {
1118        return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
1119    }
1120
1121    /**
1122     * @return The docked stack, but only if it is visible, and {@code null} otherwise.
1123     */
1124    TaskStack getDockedStackLocked() {
1125        final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
1126        return (stack != null && stack.isVisible()) ? stack : null;
1127    }
1128
1129    /**
1130     * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
1131     * visible.
1132     */
1133    TaskStack getDockedStackIgnoringVisibility() {
1134        return mService.mStackIdToStack.get(DOCKED_STACK_ID);
1135    }
1136
1137    /** Find the visible, touch-deliverable window under the given point */
1138    WindowState getTouchableWinAtPointLocked(float xf, float yf) {
1139        WindowState touchedWin = null;
1140        final int x = (int) xf;
1141        final int y = (int) yf;
1142
1143        for (int i = mWindows.size() - 1; i >= 0; i--) {
1144            WindowState window = mWindows.get(i);
1145            final int flags = window.mAttrs.flags;
1146            if (!window.isVisibleLw()) {
1147                continue;
1148            }
1149            if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
1150                continue;
1151            }
1152
1153            window.getVisibleBounds(mTmpRect);
1154            if (!mTmpRect.contains(x, y)) {
1155                continue;
1156            }
1157
1158            window.getTouchableRegion(mTmpRegion);
1159
1160            final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
1161            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
1162                touchedWin = window;
1163                break;
1164            }
1165        }
1166
1167        return touchedWin;
1168    }
1169
1170    boolean canAddToastWindowForUid(int uid) {
1171        // We allow one toast window per UID being shown at a time.
1172        final int windowCount = mWindows.size();
1173        for (int i = 0; i < windowCount; i++) {
1174            final WindowState window = mWindows.get(i);
1175            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
1176                    && !window.mPermanentlyHidden && !window.mWindowRemovalAllowed) {
1177                return false;
1178            }
1179        }
1180        return true;
1181    }
1182
1183    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
1184        if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
1185            return;
1186        }
1187        final int lostFocusUid = oldFocus.mOwnerUid;
1188        final int windowCount = mWindows.size();
1189        final Handler handler = mService.mH;
1190        for (int i = 0; i < windowCount; i++) {
1191            final WindowState window = mWindows.get(i);
1192            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
1193                if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
1194                    handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
1195                            window.mAttrs.hideTimeoutMilliseconds);
1196                }
1197            }
1198        }
1199    }
1200
1201    WindowState findFocusedWindow() {
1202        final AppWindowToken focusedApp = mService.mFocusedApp;
1203
1204        for (int i = mWindows.size() - 1; i >= 0; i--) {
1205            final WindowState win = mWindows.get(i);
1206
1207            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
1208                    + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
1209
1210            if (!win.canReceiveKeys()) {
1211                continue;
1212            }
1213
1214            final AppWindowToken wtoken = win.mAppToken;
1215
1216            // If this window's application has been removed, just skip it.
1217            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
1218                if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
1219                        + (wtoken.removed ? "removed" : "sendingToBottom"));
1220                continue;
1221            }
1222
1223            if (focusedApp == null) {
1224                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
1225                        + " using new focus @ " + i + " = " + win);
1226                return win;
1227            }
1228
1229            if (!focusedApp.windowsAreFocusable()) {
1230                // Current focused app windows aren't focusable...
1231                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
1232                        + " focusable using new focus @ " + i + " = " + win);
1233                return win;
1234            }
1235
1236            // Descend through all of the app tokens and find the first that either matches
1237            // win.mAppToken (return win) or mFocusedApp (return null).
1238            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
1239                if (focusedApp.compareTo(wtoken) > 0) {
1240                    // App stack below focused app stack. No focus for you!!!
1241                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
1242                            "findFocusedWindow: Reached focused app=" + focusedApp);
1243                    return null;
1244                }
1245            }
1246
1247            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
1248                    + i + " = " + win);
1249            return win;
1250        }
1251
1252        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
1253        return null;
1254    }
1255
1256    void addAppWindowToWindowList(final WindowState win) {
1257        final IWindow client = win.mClient;
1258
1259        WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
1260        if (!tokenWindowList.isEmpty()) {
1261            addAppWindowExisting(win, tokenWindowList);
1262            return;
1263        }
1264
1265        // No windows from this token on this display
1266        if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
1267                + client.asBinder() + " (token=" + this + ")");
1268
1269        final WindowToken wToken = win.mToken;
1270
1271        // Figure out where the window should go, based on the order of applications.
1272        mTmpGetWindowOnDisplaySearchResult.reset();
1273        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1274            final TaskStack stack = mTaskStackContainers.get(i);
1275            stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1276            if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
1277                // We have reach the token we are interested in. End search.
1278                break;
1279            }
1280        }
1281
1282        WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
1283
1284        // We now know the index into the apps. If we found an app window above, that gives us the
1285        // position; else we need to look some more.
1286        if (pos != null) {
1287            // Move behind any windows attached to this one.
1288            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
1289            if (atoken != null) {
1290                tokenWindowList = getTokenWindowsOnDisplay(atoken);
1291                final int NC = tokenWindowList.size();
1292                if (NC > 0) {
1293                    WindowState bottom = tokenWindowList.get(0);
1294                    if (bottom.mSubLayer < 0) {
1295                        pos = bottom;
1296                    }
1297                }
1298            }
1299            addWindowToListBefore(win, pos);
1300            return;
1301        }
1302
1303        // Continue looking down until we find the first token that has windows on this display.
1304        mTmpGetWindowOnDisplaySearchResult.reset();
1305        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1306            final TaskStack stack = mTaskStackContainers.get(i);
1307            stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1308            if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
1309                // We have found a window after the token. End search.
1310                break;
1311            }
1312        }
1313
1314        pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
1315
1316        if (pos != null) {
1317            // Move in front of any windows attached to this one.
1318            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
1319            if (atoken != null) {
1320                final WindowState top = atoken.getTopWindow();
1321                if (top != null && top.mSubLayer >= 0) {
1322                    pos = top;
1323                }
1324            }
1325            addWindowToListAfter(win, pos);
1326            return;
1327        }
1328
1329        // Just search for the start of this layer.
1330        final int myLayer = win.mBaseLayer;
1331        int i;
1332        for (i = mWindows.size() - 1; i >= 0; --i) {
1333            final WindowState w = mWindows.get(i);
1334            // Dock divider shares the base layer with application windows, but we want to always
1335            // keep it above the application windows. The sharing of the base layer is intended
1336            // for window animations, which need to be above the dock divider for the duration
1337            // of the animation.
1338            if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
1339                break;
1340            }
1341        }
1342        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1343                "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
1344                + mWindows.size());
1345        mWindows.add(i + 1, win);
1346        mService.mWindowsChanged = true;
1347    }
1348
1349    /** Adds this non-app window to the window list. */
1350    void addNonAppWindowToWindowList(WindowState win) {
1351        // Figure out where window should go, based on layer.
1352        int i;
1353        for (i = mWindows.size() - 1; i >= 0; i--) {
1354            final WindowState otherWin = mWindows.get(i);
1355            if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
1356                // Wallpaper wanders through the window list, for example to position itself
1357                // directly behind keyguard. Because of this it will break the ordering based on
1358                // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
1359                // we don't want the new window to appear above them. An example of this is adding
1360                // of the docked stack divider. Consider a scenario with the following ordering (top
1361                // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
1362                // to land below the assist preview, so the dock divider must ignore the wallpaper,
1363                // with which it shares the base layer.
1364                break;
1365            }
1366        }
1367
1368        i++;
1369        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1370                "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
1371        mWindows.add(i, win);
1372        mService.mWindowsChanged = true;
1373    }
1374
1375    void addToWindowList(WindowState win, int index) {
1376        mService.mWindowsChanged = true;
1377        mWindows.add(index, win);
1378    }
1379
1380    boolean removeFromWindowList(WindowState win) {
1381        mService.mWindowsChanged = true;
1382        return mWindows.remove(win);
1383    }
1384
1385    private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
1386        int wpos = mWindows.indexOf(win);
1387        if (wpos < 0) {
1388            return interestingPos;
1389        }
1390
1391        if (wpos < interestingPos) interestingPos--;
1392        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
1393        mWindows.remove(wpos);
1394        mService.mWindowsChanged = true;
1395        int childWinCount = win.mChildren.size();
1396        while (childWinCount > 0) {
1397            childWinCount--;
1398            final WindowState cw = win.mChildren.get(childWinCount);
1399            int cpos = mWindows.indexOf(cw);
1400            if (cpos >= 0) {
1401                if (cpos < interestingPos) interestingPos--;
1402                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
1403                        "Temp removing child at " + cpos + ": " + cw);
1404                mWindows.remove(cpos);
1405            }
1406        }
1407        return interestingPos;
1408    }
1409
1410    void addChildWindowToWindowList(WindowState win) {
1411        final WindowState parentWindow = win.getParentWindow();
1412
1413        WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
1414
1415        // Figure out this window's ordering relative to the parent window.
1416        final int wCount = windowsOnSameDisplay.size();
1417        final int sublayer = win.mSubLayer;
1418        int largestSublayer = Integer.MIN_VALUE;
1419        WindowState windowWithLargestSublayer = null;
1420        int i;
1421        for (i = 0; i < wCount; i++) {
1422            WindowState w = windowsOnSameDisplay.get(i);
1423            final int wSublayer = w.mSubLayer;
1424            if (wSublayer >= largestSublayer) {
1425                largestSublayer = wSublayer;
1426                windowWithLargestSublayer = w;
1427            }
1428            if (sublayer < 0) {
1429                // For negative sublayers, we go below all windows in the same sublayer.
1430                if (wSublayer >= sublayer) {
1431                    addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
1432                    break;
1433                }
1434            } else {
1435                // For positive sublayers, we go above all windows in the same sublayer.
1436                if (wSublayer > sublayer) {
1437                    addWindowToListBefore(win, w);
1438                    break;
1439                }
1440            }
1441        }
1442        if (i >= wCount) {
1443            if (sublayer < 0) {
1444                addWindowToListBefore(win, parentWindow);
1445            } else {
1446                addWindowToListAfter(win,
1447                        largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
1448            }
1449        }
1450    }
1451
1452    /** Updates the layer assignment of windows on this display. */
1453    void assignWindowLayers(boolean setLayoutNeeded) {
1454        mLayersController.assignWindowLayers(this);
1455        if (setLayoutNeeded) {
1456            setLayoutNeeded();
1457        }
1458    }
1459
1460    void adjustWallpaperWindows() {
1461        mWallpaperController.adjustWallpaperWindows(this);
1462    }
1463
1464    /**
1465     * Z-orders the display window list so that:
1466     * <ul>
1467     * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
1468     *      window.
1469     * <li>Exiting application windows are at the bottom, but above the wallpaper window.
1470     * <li>All other application windows are above the exiting application windows and ordered based
1471     *      on the ordering of their stacks and tasks on the display.
1472     * <li>Non-application windows are at the very top.
1473     * </ul>
1474     * <p>
1475     * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
1476     *       surface layering is done in {@link WindowLayersController}.
1477     */
1478    void rebuildAppWindowList() {
1479        int count = mWindows.size();
1480        int i;
1481        int lastBelow = -1;
1482        int numRemoved = 0;
1483
1484        if (mRebuildTmp.length < count) {
1485            mRebuildTmp = new WindowState[count + 10];
1486        }
1487
1488        // First remove all existing app windows.
1489        i = 0;
1490        while (i < count) {
1491            final WindowState w = mWindows.get(i);
1492            if (w.mAppToken != null) {
1493                final WindowState win = mWindows.remove(i);
1494                win.mRebuilding = true;
1495                mRebuildTmp[numRemoved] = win;
1496                mService.mWindowsChanged = true;
1497                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
1498                count--;
1499                numRemoved++;
1500                continue;
1501            } else if (lastBelow == i-1) {
1502                if (w.mAttrs.type == TYPE_WALLPAPER) {
1503                    lastBelow = i;
1504                }
1505            }
1506            i++;
1507        }
1508
1509        // Keep whatever windows were below the app windows still below, by skipping them.
1510        lastBelow++;
1511        i = lastBelow;
1512
1513        // First add all of the exiting app tokens...  these are no longer in the main app list,
1514        // but still have windows shown. We put them in the back because now that the animation is
1515        // over we no longer will care about them.
1516        final int numStacks = mTaskStackContainers.size();
1517        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1518            AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
1519            int NT = exitingAppTokens.size();
1520            for (int j = 0; j < NT; j++) {
1521                i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
1522            }
1523        }
1524
1525        // And add in the still active app tokens in Z order.
1526        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1527            i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
1528        }
1529
1530        i -= lastBelow;
1531        if (i != numRemoved) {
1532            setLayoutNeeded();
1533            Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
1534                    + " windows but added " + i + " rebuildAppWindowListLocked() "
1535                    + " callers=" + Debug.getCallers(10));
1536            for (i = 0; i < numRemoved; i++) {
1537                WindowState ws = mRebuildTmp[i];
1538                if (ws.mRebuilding) {
1539                    StringWriter sw = new StringWriter();
1540                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
1541                    ws.dump(pw, "", true);
1542                    pw.flush();
1543                    Slog.w(TAG_WM, "This window was lost: " + ws);
1544                    Slog.w(TAG_WM, sw.toString());
1545                    ws.mWinAnimator.destroySurfaceLocked();
1546                }
1547            }
1548            Slog.w(TAG_WM, "Current window hierarchy:");
1549            dumpChildrenNames();
1550            Slog.w(TAG_WM, "Final window list:");
1551            dumpWindows();
1552        }
1553        Arrays.fill(mRebuildTmp, null);
1554    }
1555
1556    /** Rebuilds the display's window list and does a relayout if something changed. */
1557    void rebuildAppWindowsAndLayoutIfNeeded() {
1558        mTmpWindows.clear();
1559        mTmpWindows.addAll(mWindows);
1560
1561        rebuildAppWindowList();
1562
1563        // Set displayContent.mLayoutNeeded if window order changed.
1564        final int tmpSize = mTmpWindows.size();
1565        final int winSize = mWindows.size();
1566        int tmpNdx = 0, winNdx = 0;
1567        while (tmpNdx < tmpSize && winNdx < winSize) {
1568            // Skip over all exiting windows, they've been moved out of order.
1569            WindowState tmp;
1570            do {
1571                tmp = mTmpWindows.get(tmpNdx++);
1572            } while (tmpNdx < tmpSize && tmp.mAppToken != null && tmp.mAppToken.mIsExiting);
1573
1574            WindowState win;
1575            do {
1576                win = mWindows.get(winNdx++);
1577            } while (winNdx < winSize && win.mAppToken != null && win.mAppToken.mIsExiting);
1578
1579            if (tmp != win) {
1580                // Window order changed.
1581                setLayoutNeeded();
1582                break;
1583            }
1584        }
1585        if (tmpNdx != winNdx) {
1586            // One list was different from the other.
1587            setLayoutNeeded();
1588        }
1589        mTmpWindows.clear();
1590
1591        if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
1592                false /*updateInputWindows*/)) {
1593            assignWindowLayers(false /* setLayoutNeeded */);
1594        }
1595
1596        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
1597        mService.mWindowPlacerLocked.performSurfacePlacement();
1598        mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
1599    }
1600
1601    void updateInputWindows(InputMonitor inputMonitor, WindowState inputFocus, boolean inDrag) {
1602        final InputConsumerImpl navInputConsumer =
1603                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_NAVIGATION, mDisplayId);
1604        final InputConsumerImpl pipInputConsumer =
1605                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_PIP, mDisplayId);
1606        final InputConsumerImpl wallpaperInputConsumer =
1607                mService.mInputMonitor.getInputConsumer(INPUT_CONSUMER_WALLPAPER, mDisplayId);
1608        boolean addInputConsumerHandle = navInputConsumer != null;
1609        boolean addPipInputConsumerHandle = pipInputConsumer != null;
1610        boolean addWallpaperInputConsumerHandle = wallpaperInputConsumer != null;
1611        final Rect pipTouchableBounds = addPipInputConsumerHandle ? new Rect() : null;
1612        boolean disableWallpaperTouchEvents = false;
1613
1614        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
1615            final WindowState child = mWindows.get(winNdx);
1616            final InputChannel inputChannel = child.mInputChannel;
1617            final InputWindowHandle inputWindowHandle = child.mInputWindowHandle;
1618            if (inputChannel == null || inputWindowHandle == null || child.mRemoved
1619                    || child.isAdjustedForMinimizedDock()) {
1620                // Skip this window because it cannot possibly receive input.
1621                continue;
1622            }
1623
1624            if (addPipInputConsumerHandle
1625                    && child.getStackId() == PINNED_STACK_ID
1626                    && inputWindowHandle.layer <= pipInputConsumer.mWindowHandle.layer) {
1627                // Update the bounds of the Pip input consumer to match the Pinned stack
1628                child.getStack().getBounds(pipTouchableBounds);
1629                pipInputConsumer.mWindowHandle.touchableRegion.set(pipTouchableBounds);
1630                inputMonitor.addInputWindowHandle(pipInputConsumer.mWindowHandle);
1631                addPipInputConsumerHandle = false;
1632            }
1633
1634            if (addInputConsumerHandle
1635                    && inputWindowHandle.layer <= navInputConsumer.mWindowHandle.layer) {
1636                inputMonitor.addInputWindowHandle(navInputConsumer.mWindowHandle);
1637                addInputConsumerHandle = false;
1638            }
1639
1640            if (addWallpaperInputConsumerHandle) {
1641                if (child.mAttrs.type == TYPE_WALLPAPER && child.isVisibleLw()) {
1642                    // Add the wallpaper input consumer above the first visible wallpaper.
1643                    inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
1644                    addWallpaperInputConsumerHandle = false;
1645                }
1646            }
1647
1648            final int flags = child.mAttrs.flags;
1649            final int privateFlags = child.mAttrs.privateFlags;
1650            final int type = child.mAttrs.type;
1651
1652            final boolean hasFocus = child == inputFocus;
1653            final boolean isVisible = child.isVisibleLw();
1654            if ((privateFlags & PRIVATE_FLAG_DISABLE_WALLPAPER_TOUCH_EVENTS) != 0) {
1655                disableWallpaperTouchEvents = true;
1656            }
1657            final boolean hasWallpaper = mWallpaperController.isWallpaperTarget(child)
1658                    && (privateFlags & PRIVATE_FLAG_KEYGUARD) == 0
1659                    && !disableWallpaperTouchEvents;
1660
1661            // If there's a drag in progress and 'child' is a potential drop target,
1662            // make sure it's been told about the drag
1663            if (inDrag && isVisible && isDefaultDisplay) {
1664                mService.mDragState.sendDragStartedIfNeededLw(child);
1665            }
1666
1667            inputMonitor.addInputWindowHandle(
1668                    inputWindowHandle, child, flags, type, isVisible, hasFocus, hasWallpaper);
1669        }
1670
1671        if (addWallpaperInputConsumerHandle) {
1672            // No visible wallpaper found, add the wallpaper input consumer at the end.
1673            inputMonitor.addInputWindowHandle(wallpaperInputConsumer.mWindowHandle);
1674        }
1675    }
1676
1677    /** Returns true if a leaked surface was destroyed */
1678    boolean destroyLeakedSurfaces() {
1679        boolean leakedSurface = false;
1680        final int numWindows = mWindows.size();
1681        for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
1682            final WindowState ws = mWindows.get(winNdx);
1683            final WindowStateAnimator wsa = ws.mWinAnimator;
1684            if (wsa.mSurfaceController == null) {
1685                continue;
1686            }
1687            if (!mService.mSessions.contains(wsa.mSession)) {
1688                Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
1689                        + ws + " surface=" + wsa.mSurfaceController
1690                        + " token=" + ws.mToken
1691                        + " pid=" + ws.mSession.mPid
1692                        + " uid=" + ws.mSession.mUid);
1693                wsa.destroySurface();
1694                mService.mForceRemoves.add(ws);
1695                leakedSurface = true;
1696            } else if (ws.mAppToken != null && ws.mAppToken.clientHidden) {
1697                Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
1698                        + ws + " surface=" + wsa.mSurfaceController
1699                        + " token=" + ws.mAppToken
1700                        + " saved=" + ws.hasSavedSurface());
1701                if (SHOW_TRANSACTIONS) logSurface(ws, "LEAK DESTROY", false);
1702                wsa.destroySurface();
1703                leakedSurface = true;
1704            }
1705        }
1706
1707        return leakedSurface;
1708    }
1709
1710    /** Return the list of Windows on this display associated with the input token. */
1711    WindowList getTokenWindowsOnDisplay(WindowToken token) {
1712        final WindowList windowList = new WindowList();
1713        final int count = mWindows.size();
1714        for (int i = 0; i < count; i++) {
1715            final WindowState win = mWindows.get(i);
1716            if (win.mToken == token) {
1717                windowList.add(win);
1718            }
1719        }
1720        return windowList;
1721    }
1722
1723    private void reAddToWindowList(WindowState win) {
1724        win.mToken.addWindow(win);
1725        // This is a hack to get all of the child windows added as well at the right position. Child
1726        // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
1727        int wpos = mWindows.indexOf(win);
1728        if (wpos >= 0) {
1729            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
1730            mWindows.remove(wpos);
1731            mService.mWindowsChanged = true;
1732            win.reAddWindow(wpos);
1733        }
1734    }
1735
1736    void moveInputMethodDialogs(int pos) {
1737        ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
1738
1739        final int N = dialogs.size();
1740        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
1741        for (int i = 0; i < N; i++) {
1742            pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
1743        }
1744        if (DEBUG_INPUT_METHOD) {
1745            Slog.v(TAG_WM, "Window list w/pos=" + pos);
1746            logWindowList(mWindows, "  ");
1747        }
1748
1749        WindowState ime = mService.mInputMethodWindow;
1750        if (pos >= 0) {
1751            // Skip windows owned by the input method.
1752            if (ime != null) {
1753                while (pos < mWindows.size()) {
1754                    WindowState wp = mWindows.get(pos);
1755                    if (wp == ime || wp.getParentWindow() == ime) {
1756                        pos++;
1757                        continue;
1758                    }
1759                    break;
1760                }
1761            }
1762            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
1763            for (int i=0; i<N; i++) {
1764                WindowState win = dialogs.get(i);
1765                pos = win.reAddWindow(pos);
1766            }
1767            if (DEBUG_INPUT_METHOD) {
1768                Slog.v(TAG_WM, "Final window list:");
1769                logWindowList(mWindows, "  ");
1770            }
1771            return;
1772        }
1773        for (int i=0; i<N; i++) {
1774            WindowState win = dialogs.get(i);
1775            reAddToWindowList(win);
1776            if (DEBUG_INPUT_METHOD) {
1777                Slog.v(TAG_WM, "No IM target, final list:");
1778                logWindowList(mWindows, "  ");
1779            }
1780        }
1781    }
1782
1783    boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
1784        final WindowState imWin = mService.mInputMethodWindow;
1785        final int DN = mService.mInputMethodDialogs.size();
1786        if (imWin == null && DN == 0) {
1787            return false;
1788        }
1789
1790        // TODO(multidisplay): IMEs are only supported on the default display.
1791        int imPos = findDesiredInputMethodWindowIndex(true);
1792        if (imPos >= 0) {
1793            // In this case, the input method windows are to be placed
1794            // immediately above the window they are targeting.
1795
1796            // First check to see if the input method windows are already
1797            // located here, and contiguous.
1798            final int N = mWindows.size();
1799            final WindowState firstImWin = imPos < N ? mWindows.get(imPos) : null;
1800
1801            // Figure out the actual input method window that should be
1802            // at the bottom of their stack.
1803            WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
1804            final WindowState cw = baseImWin.getBottomChild();
1805            if (cw != null && cw.mSubLayer < 0) {
1806                baseImWin = cw;
1807            }
1808
1809            if (firstImWin == baseImWin) {
1810                // The windows haven't moved...  but are they still contiguous?
1811                // First find the top IM window.
1812                int pos = imPos+1;
1813                while (pos < N) {
1814                    if (!(mWindows.get(pos)).mIsImWindow) {
1815                        break;
1816                    }
1817                    pos++;
1818                }
1819                pos++;
1820                // Now there should be no more input method windows above.
1821                while (pos < N) {
1822                    if ((mWindows.get(pos)).mIsImWindow) {
1823                        break;
1824                    }
1825                    pos++;
1826                }
1827                if (pos >= N) {
1828                    return false;
1829                }
1830            }
1831
1832            if (imWin != null) {
1833                if (DEBUG_INPUT_METHOD) {
1834                    Slog.v(TAG_WM, "Moving IM from " + imPos);
1835                    logWindowList(mWindows, "  ");
1836                }
1837                imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
1838                if (DEBUG_INPUT_METHOD) {
1839                    Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
1840                    logWindowList(mWindows, "  ");
1841                }
1842                imWin.reAddWindow(imPos);
1843                if (DEBUG_INPUT_METHOD) {
1844                    Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
1845                    logWindowList(mWindows, "  ");
1846                }
1847                if (DN > 0) moveInputMethodDialogs(imPos+1);
1848            } else {
1849                moveInputMethodDialogs(imPos);
1850            }
1851
1852        } else {
1853            // In this case, the input method windows go in a fixed layer,
1854            // because they aren't currently associated with a focus window.
1855
1856            if (imWin != null) {
1857                if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
1858                removeWindowAndChildrenFromWindowList(imWin, 0);
1859                reAddToWindowList(imWin);
1860                if (DEBUG_INPUT_METHOD) {
1861                    Slog.v(TAG_WM, "List with no IM target:");
1862                    logWindowList(mWindows, "  ");
1863                }
1864                if (DN > 0) moveInputMethodDialogs(-1);
1865            } else {
1866                moveInputMethodDialogs(-1);
1867            }
1868
1869        }
1870
1871        if (needAssignLayers) {
1872            assignWindowLayers(false /* setLayoutNeeded */);
1873        }
1874
1875        return true;
1876    }
1877
1878    /**
1879     * Dig through the WindowStates and find the one that the Input Method will target.
1880     * @param willMove
1881     * @return The index+1 in mWindows of the discovered target.
1882     */
1883    int findDesiredInputMethodWindowIndex(boolean willMove) {
1884        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1885        // same display. Or even when the current IME/target are not on the same screen as the next
1886        // IME/target. For now only look for input windows on the main screen.
1887        WindowState w = null;
1888        int i;
1889        for (i = mWindows.size() - 1; i >= 0; --i) {
1890            final WindowState win = mWindows.get(i);
1891
1892            if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
1893                    + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1894            if (canBeImeTarget(win)) {
1895                w = win;
1896                //Slog.i(TAG_WM, "Putting input method here!");
1897
1898                // Yet more tricksyness!  If this window is a "starting" window, we do actually want
1899                // to be on top of it, but it is not -really- where input will go.  So if the caller
1900                // is not actually looking to move the IME, look down below for a real window to
1901                // target...
1902                if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
1903                    final WindowState wb = mWindows.get(i-1);
1904                    if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1905                        i--;
1906                        w = wb;
1907                    }
1908                }
1909                break;
1910            }
1911        }
1912
1913        // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1914
1915        if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
1916
1917        // Now, a special case -- if the last target's window is in the process of exiting, and is
1918        // above the new target, keep on the last target to avoid flicker. Consider for example a
1919        // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
1920        // until it is completely gone so it doesn't drop behind the dialog or its full-screen
1921        // scrim.
1922        final WindowState curTarget = mService.mInputMethodTarget;
1923        if (curTarget != null
1924                && curTarget.isDisplayedLw()
1925                && curTarget.isClosing()
1926                && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1927            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
1928            return mWindows.indexOf(curTarget) + 1;
1929        }
1930
1931        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
1932                + w + " willMove=" + willMove);
1933
1934        if (willMove && w != null) {
1935            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1936            if (token != null) {
1937
1938                // Now some fun for dealing with window animations that modify the Z order. We need
1939                // to look at all windows below the current target that are in this app, finding the
1940                // highest visible one in layering.
1941                WindowState highestTarget = null;
1942                int highestPos = 0;
1943                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1944                    WindowList curWindows = token.getDisplayContent().mWindows;
1945                    int pos = curWindows.indexOf(curTarget);
1946                    while (pos >= 0) {
1947                        WindowState win = curWindows.get(pos);
1948                        if (win.mAppToken != token) {
1949                            break;
1950                        }
1951                        if (!win.mRemoved) {
1952                            if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1953                                    highestTarget.mWinAnimator.mAnimLayer) {
1954                                highestTarget = win;
1955                                highestPos = pos;
1956                            }
1957                        }
1958                        pos--;
1959                    }
1960                }
1961
1962                if (highestTarget != null) {
1963                    final AppTransition appTransition = mService.mAppTransition;
1964                    if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
1965                            + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1966                            + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1967                            + " new layer=" + w.mWinAnimator.mAnimLayer);
1968
1969                    if (appTransition.isTransitionSet()) {
1970                        // If we are currently setting up for an animation, hold everything until we
1971                        // can find out what will happen.
1972                        mService.mInputMethodTargetWaitingAnim = true;
1973                        mService.mInputMethodTarget = highestTarget;
1974                        return highestPos + 1;
1975                    } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1976                            highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1977                        // If the window we are currently targeting is involved with an animation,
1978                        // and it is on top of the next target we will be over, then hold off on
1979                        // moving until that is done.
1980                        mService.mInputMethodTargetWaitingAnim = true;
1981                        mService.mInputMethodTarget = highestTarget;
1982                        return highestPos + 1;
1983                    }
1984                }
1985            }
1986        }
1987
1988        //Slog.i(TAG_WM, "Placing input method @" + (i+1));
1989        if (w != null) {
1990            if (willMove) {
1991                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1992                        + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1993                mService.mInputMethodTarget = w;
1994                mService.mInputMethodTargetWaitingAnim = false;
1995                if (w.mAppToken != null) {
1996                    setInputMethodAnimLayerAdjustment(
1997                            w.mAppToken.mAppAnimator.animLayerAdjustment);
1998                } else {
1999                    setInputMethodAnimLayerAdjustment(0);
2000                }
2001            }
2002
2003            // If the docked divider is visible, we still need to go through this whole excercise to
2004            // find the appropriate input method target (used for animations and dialog
2005            // adjustments), but for purposes of Z ordering we simply wish to place it above the
2006            // docked divider. Unless it is already above the divider.
2007            final WindowState dockedDivider = mDividerControllerLocked.getWindow();
2008            if (dockedDivider != null && dockedDivider.isVisibleLw()) {
2009                int dividerIndex = mWindows.indexOf(dockedDivider);
2010                if (dividerIndex > 0 && dividerIndex > i) {
2011                    return dividerIndex + 1;
2012                }
2013            }
2014            return i+1;
2015        }
2016        if (willMove) {
2017            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
2018                    + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
2019            mService.mInputMethodTarget = null;
2020            setInputMethodAnimLayerAdjustment(0);
2021        }
2022        return -1;
2023    }
2024
2025    private static boolean canBeImeTarget(WindowState w) {
2026        final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
2027        final int type = w.mAttrs.type;
2028
2029        if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
2030                && type != TYPE_APPLICATION_STARTING) {
2031            return false;
2032        }
2033
2034        if (DEBUG_INPUT_METHOD) {
2035            Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
2036            if (!w.isVisibleOrAdding()) {
2037                Slog.i(TAG_WM, "  mSurfaceController=" + w.mWinAnimator.mSurfaceController
2038                        + " relayoutCalled=" + w.mRelayoutCalled
2039                        + " viewVis=" + w.mViewVisibility
2040                        + " policyVis=" + w.mPolicyVisibility
2041                        + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
2042                        + " parentHidden=" + w.isParentWindowHidden()
2043                        + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
2044                if (w.mAppToken != null) {
2045                    Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
2046                }
2047            }
2048        }
2049        return w.isVisibleOrAdding();
2050    }
2051
2052    private void logWindowList(final WindowList windows, String prefix) {
2053        int N = windows.size();
2054        while (N > 0) {
2055            N--;
2056            Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
2057        }
2058    }
2059
2060    boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
2061        int index = -1;
2062        while (true) {
2063            if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
2064                return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
2065            }
2066            // If we reached the bottom of the range of windows we are considering,
2067            // assume no menu is needed.
2068            if (win == bottom) {
2069                return false;
2070            }
2071            // The current window hasn't specified whether menu key is needed; look behind it.
2072            // First, we may need to determine the starting position.
2073            if (index < 0) {
2074                index = mWindows.indexOf(win);
2075            }
2076            index--;
2077            if (index < 0) {
2078                return false;
2079            }
2080            win = mWindows.get(index);
2081        }
2082    }
2083
2084    void setLayoutNeeded() {
2085        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
2086        mLayoutNeeded = true;
2087    }
2088
2089    private void clearLayoutNeeded() {
2090        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
2091        mLayoutNeeded = false;
2092    }
2093
2094    boolean isLayoutNeeded() {
2095        return mLayoutNeeded;
2096    }
2097
2098    private void addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
2099
2100        // If this application has existing windows, we simply place the new window on top of
2101        // them... but keep the starting window on top.
2102        if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
2103            // Base windows go behind everything else.
2104            final WindowState lowestWindow = tokenWindowList.get(0);
2105            addWindowToListBefore(win, lowestWindow);
2106        } else {
2107            final AppWindowToken atoken = win.mAppToken;
2108            final int windowListPos = tokenWindowList.size();
2109            final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
2110            if (atoken != null && lastWindow == atoken.startingWindow) {
2111                addWindowToListBefore(win, lastWindow);
2112            } else {
2113                int newIdx = findIdxBasedOnAppTokens(win);
2114                // There is a window above this one associated with the same apptoken note that the
2115                // window could be a floating window that was created later or a window at the top
2116                // of the list of windows associated with this token.
2117                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2118                        "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
2119                                + mWindows.size());
2120                mWindows.add(newIdx + 1, win);
2121                mService.mWindowsChanged = true;
2122            }
2123        }
2124    }
2125
2126    /** Places the first input window after the second input window in the window list. */
2127    private void addWindowToListAfter(WindowState first, WindowState second) {
2128        final int i = mWindows.indexOf(second);
2129        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2130                "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
2131                + " (after " + second + ")");
2132        mWindows.add(i + 1, first);
2133        mService.mWindowsChanged = true;
2134    }
2135
2136    /** Places the first input window before the second input window in the window list. */
2137    private void addWindowToListBefore(WindowState first, WindowState second) {
2138        int i = mWindows.indexOf(second);
2139        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
2140                "Adding window " + this + " at " + i + " of " + mWindows.size()
2141                + " (before " + second + ")");
2142        if (i < 0) {
2143            Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
2144            i = 0;
2145        }
2146        mWindows.add(i, first);
2147        mService.mWindowsChanged = true;
2148    }
2149
2150    /**
2151     * This method finds out the index of a window that has the same app token as win. used for z
2152     * ordering the windows in mWindows
2153     */
2154    private int findIdxBasedOnAppTokens(WindowState win) {
2155        for(int j = mWindows.size() - 1; j >= 0; j--) {
2156            final WindowState wentry = mWindows.get(j);
2157            if(wentry.mAppToken == win.mAppToken) {
2158                return j;
2159            }
2160        }
2161        return -1;
2162    }
2163
2164    private void dumpChildrenNames() {
2165        StringBuilder output = new StringBuilder();
2166        dumpChildrenNames(output, " ");
2167        Slog.v(TAG_WM, output.toString());
2168    }
2169
2170    private void dumpWindows() {
2171        Slog.v(TAG_WM, " Display #" + mDisplayId);
2172        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
2173            Slog.v(TAG_WM, "  #" + winNdx + ": " + mWindows.get(winNdx));
2174        }
2175    }
2176
2177    void dumpTokens(PrintWriter pw, boolean dumpAll) {
2178        if (mTokenMap.isEmpty()) {
2179            return;
2180        }
2181        pw.println("  Display #" + mDisplayId);
2182        final Iterator<WindowToken> it = mTokenMap.values().iterator();
2183        while (it.hasNext()) {
2184            final WindowToken token = it.next();
2185            pw.print("  ");
2186            pw.print(token);
2187            if (dumpAll) {
2188                pw.println(':');
2189                token.dump(pw, "    ");
2190            } else {
2191                pw.println();
2192            }
2193        }
2194    }
2195
2196    void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
2197        final int count = mWindows.size();
2198        for (int j = 0; j < count; j++) {
2199            final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator;
2200            pw.println(subPrefix + "Window #" + j + ": " + wAnim);
2201        }
2202    }
2203
2204    void enableSurfaceTrace(FileDescriptor fd) {
2205        for (int i = mWindows.size() - 1; i >= 0; i--) {
2206            final WindowState win = mWindows.get(i);
2207            win.mWinAnimator.enableSurfaceTrace(fd);
2208        }
2209    }
2210
2211    void disableSurfaceTrace() {
2212        for (int i = mWindows.size() - 1; i >= 0; i--) {
2213            final WindowState win = mWindows.get(i);
2214            win.mWinAnimator.disableSurfaceTrace();
2215        }
2216    }
2217
2218    /**
2219     * Starts the Keyguard exit animation on all windows that don't belong to an app token.
2220     */
2221    void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
2222        final WindowManagerPolicy policy = mService.mPolicy;
2223        for (int i = mWindows.size() - 1; i >= 0; i--) {
2224            final WindowState window = mWindows.get(i);
2225            if (window.mAppToken == null && policy.canBeHiddenByKeyguardLw(window)) {
2226                window.mWinAnimator.setAnimation(
2227                        policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
2228            }
2229        }
2230    }
2231
2232    boolean checkWaitingForWindows() {
2233
2234        boolean haveBootMsg = false;
2235        boolean haveApp = false;
2236        // if the wallpaper service is disabled on the device, we're never going to have
2237        // wallpaper, don't bother waiting for it
2238        boolean haveWallpaper = false;
2239        boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
2240                com.android.internal.R.bool.config_enableWallpaperService)
2241                && !mService.mOnlyCore;
2242        boolean haveKeyguard = true;
2243        final int count = mWindows.size();
2244        for (int i = 0; i < count; i++) {
2245            final WindowState w = mWindows.get(i);
2246            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
2247                return true;
2248            }
2249            if (w.isDrawnLw()) {
2250                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
2251                    haveBootMsg = true;
2252                } else if (w.mAttrs.type == TYPE_APPLICATION
2253                        || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
2254                    haveApp = true;
2255                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
2256                    haveWallpaper = true;
2257                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
2258                    haveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
2259                }
2260            }
2261        }
2262
2263        if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
2264                "******** booted=" + mService.mSystemBooted
2265                + " msg=" + mService.mShowingBootMessages
2266                + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
2267                + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
2268                + " haveKeyguard=" + haveKeyguard);
2269
2270        // If we are turning on the screen to show the boot message, don't do it until the boot
2271        // message is actually displayed.
2272        if (!mService.mSystemBooted && !haveBootMsg) {
2273            return true;
2274        }
2275
2276        // If we are turning on the screen after the boot is completed normally, don't do so until
2277        // we have the application and wallpaper.
2278        if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) ||
2279                (wallpaperEnabled && !haveWallpaper))) {
2280            return true;
2281        }
2282
2283        return false;
2284    }
2285
2286    void updateWindowsForAnimator(WindowAnimator animator) {
2287        final WallpaperController wallpaperController = mWallpaperController;
2288        for (int i = mWindows.size() - 1; i >= 0; i--) {
2289            WindowState win = mWindows.get(i);
2290            WindowStateAnimator winAnimator = win.mWinAnimator;
2291            if (winAnimator.hasSurface()) {
2292                final boolean wasAnimating = winAnimator.mWasAnimating;
2293                final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
2294                winAnimator.mWasAnimating = nowAnimating;
2295                animator.orAnimating(nowAnimating);
2296
2297                if (DEBUG_WALLPAPER) Slog.v(TAG,
2298                        win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
2299
2300                if (wasAnimating && !winAnimator.mAnimating
2301                        && wallpaperController.isWallpaperTarget(win)) {
2302                    animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2303                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2304                    if (DEBUG_LAYOUT_REPEATS) {
2305                        mService.mWindowPlacerLocked.debugLayoutRepeats(
2306                                "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
2307                    }
2308                }
2309            }
2310
2311            final AppWindowToken atoken = win.mAppToken;
2312            if (winAnimator.mDrawState == READY_TO_SHOW) {
2313                if (atoken == null || atoken.allDrawn) {
2314                    if (win.performShowLocked()) {
2315                        pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
2316                        if (DEBUG_LAYOUT_REPEATS) {
2317                            mService.mWindowPlacerLocked.debugLayoutRepeats(
2318                                    "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
2319                        }
2320                    }
2321                }
2322            }
2323            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
2324            if (appAnimator != null && appAnimator.thumbnail != null) {
2325                if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) {
2326                    appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence;
2327                    appAnimator.thumbnailLayer = 0;
2328                }
2329                if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
2330                    appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
2331                }
2332            }
2333        } // end forall windows
2334    }
2335
2336    void updateWallpaperForAnimator(WindowAnimator animator) {
2337        resetAnimationBackgroundAnimator();
2338
2339        final WindowList windows = mWindows;
2340        WindowState detachedWallpaper = null;
2341
2342        for (int i = windows.size() - 1; i >= 0; i--) {
2343            final WindowState win = windows.get(i);
2344            final WindowStateAnimator winAnimator = win.mWinAnimator;
2345            if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
2346                continue;
2347            }
2348
2349            final int flags = win.mAttrs.flags;
2350
2351            // If this window is animating, make a note that we have an animating window and take
2352            // care of a request to run a detached wallpaper animation.
2353            if (winAnimator.mAnimating) {
2354                if (winAnimator.mAnimation != null) {
2355                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
2356                            && winAnimator.mAnimation.getDetachWallpaper()) {
2357                        detachedWallpaper = win;
2358                    }
2359                    final int color = winAnimator.mAnimation.getBackgroundColor();
2360                    if (color != 0) {
2361                        final TaskStack stack = win.getStack();
2362                        if (stack != null) {
2363                            stack.setAnimationBackground(winAnimator, color);
2364                        }
2365                    }
2366                }
2367                animator.setAnimating(true);
2368            }
2369
2370            // If this window's app token is running a detached wallpaper animation, make a note so
2371            // we can ensure the wallpaper is displayed behind it.
2372            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
2373            if (appAnimator != null && appAnimator.animation != null
2374                    && appAnimator.animating) {
2375                if ((flags & FLAG_SHOW_WALLPAPER) != 0
2376                        && appAnimator.animation.getDetachWallpaper()) {
2377                    detachedWallpaper = win;
2378                }
2379
2380                final int color = appAnimator.animation.getBackgroundColor();
2381                if (color != 0) {
2382                    final TaskStack stack = win.getStack();
2383                    if (stack != null) {
2384                        stack.setAnimationBackground(winAnimator, color);
2385                    }
2386                }
2387            }
2388        } // end forall windows
2389
2390        if (animator.mWindowDetachedWallpaper != detachedWallpaper) {
2391            if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
2392                    + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper);
2393            animator.mWindowDetachedWallpaper = detachedWallpaper;
2394            animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2395        }
2396    }
2397
2398    void prepareWindowSurfaces() {
2399        final int count = mWindows.size();
2400        for (int j = 0; j < count; j++) {
2401            mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true);
2402        }
2403    }
2404
2405    boolean inputMethodClientHasFocus(IInputMethodClient client) {
2406        // The focus for the client is the window immediately below where we would place the input
2407        // method window.
2408        int idx = findDesiredInputMethodWindowIndex(false);
2409        if (idx <= 0) {
2410            return false;
2411        }
2412
2413        WindowState imFocus = mWindows.get(idx - 1);
2414        if (DEBUG_INPUT_METHOD) {
2415            Slog.i(TAG_WM, "Desired input method target: " + imFocus);
2416            Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
2417            Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
2418        }
2419
2420        if (imFocus == null) {
2421            return false;
2422        }
2423
2424        // This may be a starting window, in which case we still want to count it as okay.
2425        if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) {
2426            // The client has definitely started, so it really should have a window in this app
2427            // token. Let's look for it.
2428            final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
2429            if (w != null) {
2430                if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w);
2431                imFocus = w;
2432            }
2433        }
2434
2435        final IInputMethodClient imeClient = imFocus.mSession.mClient;
2436
2437        if (DEBUG_INPUT_METHOD) {
2438            Slog.i(TAG_WM, "IM target client: " + imeClient);
2439            if (imeClient != null) {
2440                Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
2441                Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
2442            }
2443        }
2444
2445        return imeClient != null && imeClient.asBinder() == client.asBinder();
2446    }
2447
2448    boolean hasSecureWindowOnScreen() {
2449        for (int i = mWindows.size() - 1; i >= 0; --i) {
2450            final WindowState ws = mWindows.get(i);
2451            if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
2452                return true;
2453            }
2454        }
2455        return false;
2456    }
2457
2458    void updateSystemUiVisibility(int visibility, int globalDiff) {
2459        for (int i = mWindows.size() - 1; i >= 0; --i) {
2460            final WindowState ws = mWindows.get(i);
2461            try {
2462                int curValue = ws.mSystemUiVisibility;
2463                int diff = (curValue ^ visibility) & globalDiff;
2464                int newValue = (curValue & ~diff) | (visibility & diff);
2465                if (newValue != curValue) {
2466                    ws.mSeq++;
2467                    ws.mSystemUiVisibility = newValue;
2468                }
2469                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
2470                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
2471                            visibility, newValue, diff);
2472                }
2473            } catch (RemoteException e) {
2474                // so sorry
2475            }
2476        }
2477    }
2478
2479    void onWindowFreezeTimeout() {
2480        Slog.w(TAG_WM, "Window freeze timeout expired.");
2481        mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
2482        for (int i = mWindows.size() - 1; i >= 0; --i) {
2483            final WindowState w = mWindows.get(i);
2484            if (!w.mOrientationChanging) {
2485                continue;
2486            }
2487            w.mOrientationChanging = false;
2488            w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
2489                    - mService.mDisplayFreezeTime);
2490            Slog.w(TAG_WM, "Force clearing orientation change: " + w);
2491        }
2492        mService.mWindowPlacerLocked.performSurfacePlacement();
2493    }
2494
2495    void waitForAllWindowsDrawn() {
2496        final WindowManagerPolicy policy = mService.mPolicy;
2497        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
2498            final WindowState win = mWindows.get(winNdx);
2499            final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
2500            if (win.isVisibleLw() && (win.mAppToken != null || keyguard)) {
2501                win.mWinAnimator.mDrawState = DRAW_PENDING;
2502                // Force add to mResizingWindows.
2503                win.mLastContentInsets.set(-1, -1, -1, -1);
2504                mService.mWaitingForDrawn.add(win);
2505            }
2506        }
2507    }
2508
2509    // TODO: Super crazy long method that should be broken down...
2510    boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
2511
2512        boolean focusDisplayed = false;
2513        boolean displayHasContent = false;
2514        float preferredRefreshRate = 0;
2515        int preferredModeId = 0;
2516
2517
2518        final int dw = mDisplayInfo.logicalWidth;
2519        final int dh = mDisplayInfo.logicalHeight;
2520        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
2521
2522        mTmpUpdateAllDrawn.clear();
2523
2524        int repeats = 0;
2525        do {
2526            repeats++;
2527            if (repeats > 6) {
2528                Slog.w(TAG, "Animation repeat aborted after too many iterations");
2529                clearLayoutNeeded();
2530                break;
2531            }
2532
2533            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
2534                    pendingLayoutChanges);
2535
2536            // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
2537            // the wallpaper window jumping across displays.
2538            // Remove check for default display when there will be support for multiple wallpaper
2539            // targets (on different displays).
2540            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
2541                adjustWallpaperWindows();
2542            }
2543
2544            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
2545                if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
2546                if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
2547                    setLayoutNeeded();
2548                    mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
2549                }
2550            }
2551
2552            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
2553                setLayoutNeeded();
2554            }
2555
2556            // FIRST LOOP: Perform a layout, if needed.
2557            if (repeats < LAYOUT_REPEAT_THRESHOLD) {
2558                performLayout(repeats == 1, false /* updateInputWindows */);
2559            } else {
2560                Slog.w(TAG, "Layout repeat skipped after too many iterations");
2561            }
2562
2563            // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
2564            pendingLayoutChanges = 0;
2565
2566            if (isDefaultDisplay) {
2567                mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
2568                for (int i = mWindows.size() - 1; i >= 0; i--) {
2569                    final WindowState w = mWindows.get(i);
2570                    mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
2571                            mService.mInputMethodTarget);
2572                }
2573                pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
2574                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
2575                        "after finishPostLayoutPolicyLw", pendingLayoutChanges);
2576            }
2577        } while (pendingLayoutChanges != 0);
2578
2579        RootWindowContainer root = mService.mRoot;
2580        boolean obscured = false;
2581        boolean syswin = false;
2582        resetDimming();
2583
2584        // Only used if default window
2585        final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
2586
2587        for (int i = mWindows.size() - 1; i >= 0; i--) {
2588            final WindowState w = mWindows.get(i);
2589            final Task task = w.getTask();
2590            final boolean obscuredChanged = w.mObscured != obscured;
2591
2592            // Update effect.
2593            w.mObscured = obscured;
2594            if (!obscured) {
2595                final boolean isDisplayed = w.isDisplayedLw();
2596
2597                if (isDisplayed && w.isObscuringDisplay()) {
2598                    // This window completely covers everything behind it, so we want to leave all
2599                    // of them as undimmed (for performance reasons).
2600                    root.mObscuringWindow = w;
2601                    obscured = true;
2602                }
2603
2604                displayHasContent |= root.handleNotObscuredLocked(w, obscured, syswin);
2605
2606                if (w.mHasSurface && isDisplayed) {
2607                    final int type = w.mAttrs.type;
2608                    if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
2609                            || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
2610                        syswin = true;
2611                    }
2612                    if (preferredRefreshRate == 0 && w.mAttrs.preferredRefreshRate != 0) {
2613                        preferredRefreshRate = w.mAttrs.preferredRefreshRate;
2614                    }
2615                    if (preferredModeId == 0 && w.mAttrs.preferredDisplayModeId != 0) {
2616                        preferredModeId = w.mAttrs.preferredDisplayModeId;
2617                    }
2618                }
2619            }
2620
2621            w.applyDimLayerIfNeeded();
2622
2623            if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
2624                    && mWallpaperController.isWallpaperTarget(w)) {
2625                // This is the wallpaper target and its obscured state changed... make sure the
2626                // current wallpaper's visibility has been updated accordingly.
2627                mWallpaperController.updateWallpaperVisibility();
2628            }
2629
2630            w.handleWindowMovedIfNeeded();
2631
2632            final WindowStateAnimator winAnimator = w.mWinAnimator;
2633
2634            //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
2635            w.mContentChanged = false;
2636
2637            // Moved from updateWindowsAndWallpaperLocked().
2638            if (w.mHasSurface) {
2639                // Take care of the window being ready to display.
2640                final boolean committed = winAnimator.commitFinishDrawingLocked();
2641                if (isDefaultDisplay && committed) {
2642                    if (w.mAttrs.type == TYPE_DREAM) {
2643                        // HACK: When a dream is shown, it may at that point hide the lock screen.
2644                        // So we need to redo the layout to let the phone window manager make this
2645                        // happen.
2646                        pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
2647                        if (DEBUG_LAYOUT_REPEATS) {
2648                            surfacePlacer.debugLayoutRepeats(
2649                                    "dream and commitFinishDrawingLocked true",
2650                                    pendingLayoutChanges);
2651                        }
2652                    }
2653                    if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
2654                        if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
2655                                "First draw done in potential wallpaper target " + w);
2656                        root.mWallpaperMayChange = true;
2657                        pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2658                        if (DEBUG_LAYOUT_REPEATS) {
2659                            surfacePlacer.debugLayoutRepeats(
2660                                    "wallpaper and commitFinishDrawingLocked true",
2661                                    pendingLayoutChanges);
2662                        }
2663                    }
2664                }
2665                if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
2666                    // Updates the shown frame before we set up the surface. This is needed
2667                    // because the resizing could change the top-left position (in addition to
2668                    // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
2669                    // position the surface.
2670                    //
2671                    // If an animation is being started, we can't call this method because the
2672                    // animation hasn't processed its initial transformation yet, but in general
2673                    // we do want to update the position if the window is animating.
2674                    winAnimator.computeShownFrameLocked();
2675                }
2676                winAnimator.setSurfaceBoundariesLocked(recoveringMemory);
2677            }
2678
2679            final AppWindowToken atoken = w.mAppToken;
2680            if (atoken != null) {
2681                final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
2682                if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
2683                    mTmpUpdateAllDrawn.add(atoken);
2684                }
2685            }
2686
2687            if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
2688                    && w.isDisplayedLw()) {
2689                focusDisplayed = true;
2690            }
2691
2692            w.updateResizingWindowIfNeeded();
2693        }
2694
2695        mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
2696                displayHasContent,
2697                preferredRefreshRate,
2698                preferredModeId,
2699                true /* inTraversal, must call performTraversalInTrans... below */);
2700
2701        stopDimmingIfNeeded();
2702
2703        while (!mTmpUpdateAllDrawn.isEmpty()) {
2704            final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
2705            // See if any windows have been drawn, so they (and others associated with them)
2706            // can now be shown.
2707            atoken.updateAllDrawn(this);
2708        }
2709
2710        return focusDisplayed;
2711    }
2712
2713    void performLayout(boolean initial, boolean updateInputWindows) {
2714        if (!isLayoutNeeded()) {
2715            return;
2716        }
2717        clearLayoutNeeded();
2718
2719        final int dw = mDisplayInfo.logicalWidth;
2720        final int dh = mDisplayInfo.logicalHeight;
2721
2722        int i;
2723
2724        if (DEBUG_LAYOUT) {
2725            Slog.v(TAG, "-------------------------------------");
2726            Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
2727        }
2728
2729        mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
2730                getConfiguration().uiMode);
2731        if (isDefaultDisplay) {
2732            // Not needed on non-default displays.
2733            mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
2734            mService.mScreenRect.set(0, 0, dw, dh);
2735        }
2736
2737        mService.mPolicy.getContentRectLw(mContentRect);
2738
2739        int seq = mService.mLayoutSeq + 1;
2740        if (seq < 0) seq = 0;
2741        mService.mLayoutSeq = seq;
2742
2743        boolean behindDream = false;
2744
2745        // First perform layout of any root windows (not attached to another window).
2746        int topAttached = -1;
2747        for (i = mWindows.size() - 1; i >= 0; i--) {
2748            final WindowState win = mWindows.get(i);
2749
2750            // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
2751            // wasting time and funky changes while a window is animating away.
2752            final boolean gone = (behindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win))
2753                    || win.isGoneForLayoutLw();
2754
2755            if (DEBUG_LAYOUT && !win.mLayoutAttached) {
2756                Slog.v(TAG, "1ST PASS " + win + ": gone=" + gone + " mHaveFrame=" + win.mHaveFrame
2757                        + " mLayoutAttached=" + win.mLayoutAttached
2758                        + " screen changed=" + win.isConfigChanged());
2759                final AppWindowToken atoken = win.mAppToken;
2760                if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + win.mViewVisibility
2761                        + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
2762                        + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
2763                        + " parentHidden=" + win.isParentWindowHidden());
2764                else Slog.v(TAG, "  VIS: mViewVisibility=" + win.mViewVisibility
2765                        + " mRelayoutCalled=" + win.mRelayoutCalled + " hidden=" + win.mToken.hidden
2766                        + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
2767                        + " parentHidden=" + win.isParentWindowHidden());
2768            }
2769
2770            // If this view is GONE, then skip it -- keep the current frame, and let the caller know
2771            // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
2772            // since that means "perform layout as normal, just don't display").
2773            if (!gone || !win.mHaveFrame || win.mLayoutNeeded
2774                    || ((win.isConfigChanged() || win.setReportResizeHints())
2775                    && !win.isGoneForLayoutLw() &&
2776                    ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
2777                            (win.mHasSurface && win.mAppToken != null &&
2778                                    win.mAppToken.layoutConfigChanges)))) {
2779                if (!win.mLayoutAttached) {
2780                    if (initial) {
2781                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
2782                        win.mContentChanged = false;
2783                    }
2784                    if (win.mAttrs.type == TYPE_DREAM) {
2785                        // Don't layout windows behind a dream, so that if it does stuff like hide
2786                        // the status bar we won't get a bad transition when it goes away.
2787                        behindDream = true;
2788                    }
2789                    win.mLayoutNeeded = false;
2790                    win.prelayout();
2791                    mService.mPolicy.layoutWindowLw(win, null);
2792                    win.mLayoutSeq = seq;
2793
2794                    // Window frames may have changed. Update dim layer with the new bounds.
2795                    final Task task = win.getTask();
2796                    if (task != null) {
2797                        mDimLayerController.updateDimLayer(task);
2798                    }
2799
2800                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + win.mFrame
2801                            + " mContainingFrame=" + win.mContainingFrame
2802                            + " mDisplayFrame=" + win.mDisplayFrame);
2803                } else {
2804                    if (topAttached < 0) topAttached = i;
2805                }
2806            }
2807        }
2808
2809        boolean attachedBehindDream = false;
2810
2811        // Now perform layout of attached windows, which usually depend on the position of the
2812        // window they are attached to. XXX does not deal with windows that are attached to windows
2813        // that are themselves attached.
2814        for (i = topAttached; i >= 0; i--) {
2815            final WindowState win = mWindows.get(i);
2816
2817            if (win.mLayoutAttached) {
2818                if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + win + " mHaveFrame=" + win.mHaveFrame
2819                        + " mViewVisibility=" + win.mViewVisibility
2820                        + " mRelayoutCalled=" + win.mRelayoutCalled);
2821                // If this view is GONE, then skip it -- keep the current frame, and let the caller
2822                // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
2823                // windows, since that means "perform layout as normal, just don't display").
2824                if (attachedBehindDream && mService.mPolicy.canBeHiddenByKeyguardLw(win)) {
2825                    continue;
2826                }
2827                if ((win.mViewVisibility != GONE && win.mRelayoutCalled) || !win.mHaveFrame
2828                        || win.mLayoutNeeded) {
2829                    if (initial) {
2830                        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
2831                        win.mContentChanged = false;
2832                    }
2833                    win.mLayoutNeeded = false;
2834                    win.prelayout();
2835                    mService.mPolicy.layoutWindowLw(win, win.getParentWindow());
2836                    win.mLayoutSeq = seq;
2837                    if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + win.mFrame
2838                            + " mContainingFrame=" + win.mContainingFrame
2839                            + " mDisplayFrame=" + win.mDisplayFrame);
2840                }
2841            } else if (win.mAttrs.type == TYPE_DREAM) {
2842                // Don't layout windows behind a dream, so that if it does stuff like hide the
2843                // status bar we won't get a bad transition when it goes away.
2844                attachedBehindDream = behindDream;
2845            }
2846        }
2847
2848        // Window frames may have changed. Tell the input dispatcher about it.
2849        mService.mInputMonitor.layoutInputConsumers(dw, dh);
2850        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
2851        if (updateInputWindows) {
2852            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
2853        }
2854
2855        mService.mPolicy.finishLayoutLw();
2856        mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
2857    }
2858
2859    /**
2860     * Takes a snapshot of the display.  In landscape mode this grabs the whole screen.
2861     * In portrait mode, it grabs the full screenshot.
2862     *
2863     * @param width the width of the target bitmap
2864     * @param height the height of the target bitmap
2865     * @param includeFullDisplay true if the screen should not be cropped before capture
2866     * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
2867     * @param config of the output bitmap
2868     * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
2869     */
2870    Bitmap screenshotApplications(IBinder appToken, int displayId, int width, int height,
2871            boolean includeFullDisplay, float frameScale, Bitmap.Config config,
2872            boolean wallpaperOnly) {
2873        int dw = mDisplayInfo.logicalWidth;
2874        int dh = mDisplayInfo.logicalHeight;
2875        if (dw == 0 || dh == 0) {
2876            if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2877                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
2878            return null;
2879        }
2880
2881        Bitmap bm = null;
2882
2883        int maxLayer = 0;
2884        final Rect frame = new Rect();
2885        final Rect stackBounds = new Rect();
2886
2887        boolean screenshotReady;
2888        int minLayer;
2889        if (appToken == null && !wallpaperOnly) {
2890            screenshotReady = true;
2891            minLayer = 0;
2892        } else {
2893            screenshotReady = false;
2894            minLayer = Integer.MAX_VALUE;
2895        }
2896
2897        WindowState appWin = null;
2898
2899        boolean includeImeInScreenshot;
2900        synchronized(mService.mWindowMap) {
2901            final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
2902                    ? mService.mInputMethodTarget.mAppToken : null;
2903            // We only include the Ime in the screenshot if the app we are screenshoting is the IME
2904            // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
2905            // mode because the frame of the IME might not overlap with that of the app.
2906            // E.g. IME target app at the top in split-screen mode and the IME at the bottom
2907            // overlapping with the bottom app.
2908            includeImeInScreenshot = imeTargetAppToken != null
2909                    && imeTargetAppToken.appToken != null
2910                    && imeTargetAppToken.appToken.asBinder() == appToken
2911                    && !mService.mInputMethodTarget.isInMultiWindowMode();
2912        }
2913
2914        final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
2915                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
2916
2917        synchronized(mService.mWindowMap) {
2918            // Figure out the part of the screen that is actually the app.
2919            appWin = null;
2920            for (int i = mWindows.size() - 1; i >= 0; i--) {
2921                final WindowState ws = mWindows.get(i);
2922                if (!ws.mHasSurface) {
2923                    continue;
2924                }
2925                if (ws.mLayer >= aboveAppLayer) {
2926                    continue;
2927                }
2928                if (wallpaperOnly && !ws.mIsWallpaper) {
2929                    continue;
2930                }
2931                if (ws.mIsImWindow) {
2932                    if (!includeImeInScreenshot) {
2933                        continue;
2934                    }
2935                } else if (ws.mIsWallpaper) {
2936                    // If this is the wallpaper layer and we're only looking for the wallpaper layer
2937                    // then the target window state is this one.
2938                    if (wallpaperOnly) {
2939                        appWin = ws;
2940                    }
2941
2942                    if (appWin == null) {
2943                        // We have not ran across the target window yet, so it is probably behind
2944                        // the wallpaper. This can happen when the keyguard is up and all windows
2945                        // are moved behind the wallpaper. We don't want to include the wallpaper
2946                        // layer in the screenshot as it will cover-up the layer of the target
2947                        // window.
2948                        continue;
2949                    }
2950                    // Fall through. The target window is in front of the wallpaper. For this
2951                    // case we want to include the wallpaper layer in the screenshot because
2952                    // the target window might have some transparent areas.
2953                } else if (appToken != null) {
2954                    if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
2955                        // This app window is of no interest if it is not associated with the
2956                        // screenshot app.
2957                        continue;
2958                    }
2959                    appWin = ws;
2960                }
2961
2962                // Include this window.
2963
2964                final WindowStateAnimator winAnim = ws.mWinAnimator;
2965                int layer = winAnim.mSurfaceController.getLayer();
2966                if (maxLayer < layer) {
2967                    maxLayer = layer;
2968                }
2969                if (minLayer > layer) {
2970                    minLayer = layer;
2971                }
2972
2973                // Don't include wallpaper in bounds calculation
2974                if (!includeFullDisplay && !ws.mIsWallpaper) {
2975                    final Rect wf = ws.mFrame;
2976                    final Rect cr = ws.mContentInsets;
2977                    int left = wf.left + cr.left;
2978                    int top = wf.top + cr.top;
2979                    int right = wf.right - cr.right;
2980                    int bottom = wf.bottom - cr.bottom;
2981                    frame.union(left, top, right, bottom);
2982                    ws.getVisibleBounds(stackBounds);
2983                    if (!Rect.intersects(frame, stackBounds)) {
2984                        // Set frame empty if there's no intersection.
2985                        frame.setEmpty();
2986                    }
2987                }
2988
2989                final boolean foundTargetWs =
2990                        (ws.mAppToken != null && ws.mAppToken.token == appToken)
2991                                || (appWin != null && wallpaperOnly);
2992                if (foundTargetWs && ws.isDisplayedLw() && winAnim.getShown()) {
2993                    screenshotReady = true;
2994                }
2995
2996                if (ws.isObscuringDisplay()){
2997                    break;
2998                }
2999            }
3000
3001            if (appToken != null && appWin == null) {
3002                // Can't find a window to snapshot.
3003                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
3004                        "Screenshot: Couldn't find a surface matching " + appToken);
3005                return null;
3006            }
3007
3008            if (!screenshotReady) {
3009                Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
3010                        " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
3011                        appWin.mWinAnimator.mDrawState)));
3012                return null;
3013            }
3014
3015            // Screenshot is ready to be taken. Everything from here below will continue
3016            // through the bottom of the loop and return a value. We only stay in the loop
3017            // because we don't want to release the mWindowMap lock until the screenshot is
3018            // taken.
3019
3020            if (maxLayer == 0) {
3021                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
3022                        + ": returning null maxLayer=" + maxLayer);
3023                return null;
3024            }
3025
3026            if (!includeFullDisplay) {
3027                // Constrain frame to the screen size.
3028                if (!frame.intersect(0, 0, dw, dh)) {
3029                    frame.setEmpty();
3030                }
3031            } else {
3032                // Caller just wants entire display.
3033                frame.set(0, 0, dw, dh);
3034            }
3035            if (frame.isEmpty()) {
3036                return null;
3037            }
3038
3039            if (width < 0) {
3040                width = (int) (frame.width() * frameScale);
3041            }
3042            if (height < 0) {
3043                height = (int) (frame.height() * frameScale);
3044            }
3045
3046            // Tell surface flinger what part of the image to crop. Take the top
3047            // right part of the application, and crop the larger dimension to fit.
3048            Rect crop = new Rect(frame);
3049            if (width / (float) frame.width() < height / (float) frame.height()) {
3050                int cropWidth = (int)((float)width / (float)height * frame.height());
3051                crop.right = crop.left + cropWidth;
3052            } else {
3053                int cropHeight = (int)((float)height / (float)width * frame.width());
3054                crop.bottom = crop.top + cropHeight;
3055            }
3056
3057            // The screenshot API does not apply the current screen rotation.
3058            int rot = mDisplay.getRotation();
3059
3060            if (rot == ROTATION_90 || rot == ROTATION_270) {
3061                rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
3062            }
3063
3064            // Surfaceflinger is not aware of orientation, so convert our logical
3065            // crop to surfaceflinger's portrait orientation.
3066            convertCropForSurfaceFlinger(crop, rot, dw, dh);
3067
3068            if (DEBUG_SCREENSHOT) {
3069                Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
3070                        + maxLayer + " appToken=" + appToken);
3071                for (int i = 0; i < mWindows.size(); i++) {
3072                    final WindowState win = mWindows.get(i);
3073                    final WindowSurfaceController controller = win.mWinAnimator.mSurfaceController;
3074                    Slog.i(TAG_WM, win + ": " + win.mLayer
3075                            + " animLayer=" + win.mWinAnimator.mAnimLayer
3076                            + " surfaceLayer=" + ((controller == null)
3077                            ? "null" : controller.getLayer()));
3078                }
3079            }
3080
3081            final ScreenRotationAnimation screenRotationAnimation =
3082                    mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
3083            final boolean inRotation = screenRotationAnimation != null &&
3084                    screenRotationAnimation.isAnimating();
3085            if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
3086                    "Taking screenshot while rotating");
3087
3088            // We force pending transactions to flush before taking
3089            // the screenshot by pushing an empty synchronous transaction.
3090            SurfaceControl.openTransaction();
3091            SurfaceControl.closeTransactionSync();
3092
3093            bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
3094                    inRotation, rot);
3095            if (bm == null) {
3096                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
3097                        + ") to layer " + maxLayer);
3098                return null;
3099            }
3100        }
3101
3102        if (DEBUG_SCREENSHOT) {
3103            // TEST IF IT's ALL BLACK
3104            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
3105            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
3106            boolean allBlack = true;
3107            final int firstColor = buffer[0];
3108            for (int i = 0; i < buffer.length; i++) {
3109                if (buffer[i] != firstColor) {
3110                    allBlack = false;
3111                    break;
3112                }
3113            }
3114            if (allBlack) {
3115                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
3116                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
3117                        (appWin != null ?
3118                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
3119                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
3120            }
3121        }
3122
3123        // Create a copy of the screenshot that is immutable and backed in ashmem.
3124        // This greatly reduces the overhead of passing the bitmap between processes.
3125        Bitmap ret = bm.createAshmemBitmap(config);
3126        bm.recycle();
3127        return ret;
3128    }
3129
3130    // TODO: Can this use createRotationMatrix()?
3131    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
3132        if (rot == Surface.ROTATION_90) {
3133            final int tmp = crop.top;
3134            crop.top = dw - crop.right;
3135            crop.right = crop.bottom;
3136            crop.bottom = dw - crop.left;
3137            crop.left = tmp;
3138        } else if (rot == Surface.ROTATION_180) {
3139            int tmp = crop.top;
3140            crop.top = dh - crop.bottom;
3141            crop.bottom = dh - tmp;
3142            tmp = crop.right;
3143            crop.right = dw - crop.left;
3144            crop.left = dw - tmp;
3145        } else if (rot == Surface.ROTATION_270) {
3146            final int tmp = crop.top;
3147            crop.top = crop.left;
3148            crop.left = dh - crop.bottom;
3149            crop.bottom = crop.right;
3150            crop.right = dh - tmp;
3151        }
3152    }
3153
3154    void onSeamlessRotationTimeout() {
3155        boolean layoutNeeded = false;
3156        for (int i = mWindows.size() - 1; i >= 0; i--) {
3157            final WindowState w = mWindows.get(i);
3158            if (!w.mSeamlesslyRotated) {
3159                continue;
3160            }
3161            layoutNeeded = true;
3162            w.setDisplayLayoutNeeded();
3163            mService.markForSeamlessRotation(w, false);
3164        }
3165
3166        if (layoutNeeded) {
3167            mService.mWindowPlacerLocked.performSurfacePlacement();
3168        }
3169    }
3170
3171    static final class GetWindowOnDisplaySearchResult {
3172        boolean reachedToken;
3173        WindowState foundWindow;
3174
3175        void reset() {
3176            reachedToken = false;
3177            foundWindow = null;
3178        }
3179    }
3180
3181    static final class TaskForResizePointSearchResult {
3182        boolean searchDone;
3183        Task taskForResize;
3184
3185        void reset() {
3186            searchDone = false;
3187            taskForResize = null;
3188        }
3189    }
3190
3191    /**
3192     * Base class for any direct child window container of {@link #DisplayContent} need to inherit
3193     * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
3194     * homogeneous children type which is currently required by sub-classes of
3195     * {@link WindowContainer} class.
3196     */
3197    static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
3198
3199        int size() {
3200            return mChildren.size();
3201        }
3202
3203        E get(int index) {
3204            return mChildren.get(index);
3205        }
3206
3207        @Override
3208        boolean fillsParent() {
3209            return true;
3210        }
3211
3212        @Override
3213        boolean isVisible() {
3214            return true;
3215        }
3216    }
3217
3218    /**
3219     * Window container class that contains all containers on this display relating to Apps.
3220     * I.e Activities.
3221     */
3222    private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
3223
3224        /**
3225         * Adds the stack to this container.
3226         * @see WindowManagerService#addStackToDisplay(int, int, boolean)
3227         */
3228        void addStackToDisplay(TaskStack stack, boolean onTop) {
3229            if (stack.mStackId == HOME_STACK_ID) {
3230                if (mHomeStack != null) {
3231                    throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
3232                }
3233                mHomeStack = stack;
3234            }
3235            addChild(stack, onTop);
3236            stack.onDisplayChanged(DisplayContent.this);
3237        }
3238
3239        /** Removes the stack from its container and prepare for changing the parent. */
3240        void removeStackFromDisplay(TaskStack stack) {
3241            removeChild(stack);
3242            stack.onRemovedFromDisplay();
3243            // TODO: remove when window list will be gone.
3244            // Manually remove records from window list and tap excluded windows list.
3245            for (int i = mWindows.size() - 1; i >= 0; --i) {
3246                final WindowState windowState = mWindows.get(i);
3247                if (stack == windowState.getStack()) {
3248                    mWindows.remove(i);
3249                    mTapExcludedWindows.remove(windowState);
3250                }
3251            }
3252        }
3253
3254        void moveStack(TaskStack stack, boolean toTop) {
3255            if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
3256                // This stack is always-on-top silly...
3257                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
3258                return;
3259            }
3260
3261            if (!mChildren.contains(stack)) {
3262                Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
3263            }
3264            removeChild(stack);
3265            addChild(stack, toTop);
3266        }
3267
3268        private void addChild(TaskStack stack, boolean toTop) {
3269            int addIndex = toTop ? mChildren.size() : 0;
3270
3271            if (toTop
3272                    && mService.isStackVisibleLocked(PINNED_STACK_ID)
3273                    && stack.mStackId != PINNED_STACK_ID) {
3274                // The pinned stack is always the top most stack (always-on-top) when it is visible.
3275                // So, stack is moved just below the pinned stack.
3276                addIndex--;
3277                TaskStack topStack = mChildren.get(addIndex);
3278                if (topStack.mStackId != PINNED_STACK_ID) {
3279                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
3280                }
3281            }
3282            addChild(stack, addIndex);
3283            setLayoutNeeded();
3284        }
3285
3286        @Override
3287        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
3288                boolean traverseTopToBottom) {
3289            if (traverseTopToBottom) {
3290                if (super.forAllWindows(callback, traverseTopToBottom)) {
3291                    return true;
3292                }
3293                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
3294                    return true;
3295                }
3296            } else {
3297                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
3298                    return true;
3299                }
3300                if (super.forAllWindows(callback, traverseTopToBottom)) {
3301                    return true;
3302                }
3303            }
3304            return false;
3305        }
3306
3307        private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
3308                boolean traverseTopToBottom) {
3309            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
3310            // app tokens.
3311            // TODO: Investigate if we need to continue to do this or if we can just process them
3312            // in-order.
3313            if (traverseTopToBottom) {
3314                for (int i = mChildren.size() - 1; i >= 0; --i) {
3315                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3316                    for (int j = appTokens.size() - 1; j >= 0; --j) {
3317                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
3318                                traverseTopToBottom)) {
3319                            return true;
3320                        }
3321                    }
3322                }
3323            } else {
3324                final int count = mChildren.size();
3325                for (int i = 0; i < count; ++i) {
3326                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
3327                    final int appTokensCount = appTokens.size();
3328                    for (int j = 0; j < appTokensCount; j++) {
3329                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
3330                                traverseTopToBottom)) {
3331                            return true;
3332                        }
3333                    }
3334                }
3335            }
3336            return false;
3337        }
3338
3339        @Override
3340        int getOrientation() {
3341            if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
3342                    || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
3343                // Apps and their containers are not allowed to specify an orientation while the
3344                // docked or freeform stack is visible...except for the home stack/task if the
3345                // docked stack is minimized and it actually set something.
3346                if (mHomeStack != null && mHomeStack.isVisible()
3347                        && mDividerControllerLocked.isMinimizedDock()) {
3348                    final int orientation = mHomeStack.getOrientation();
3349                    if (orientation != SCREEN_ORIENTATION_UNSET) {
3350                        return orientation;
3351                    }
3352                }
3353                return SCREEN_ORIENTATION_UNSPECIFIED;
3354            }
3355
3356            final int orientation = super.getOrientation();
3357            if (orientation != SCREEN_ORIENTATION_UNSET
3358                    && orientation != SCREEN_ORIENTATION_BEHIND) {
3359                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3360                        "App is requesting an orientation, return " + orientation);
3361                return orientation;
3362            }
3363
3364            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
3365                    "No app is requesting an orientation, return " + mService.mLastOrientation);
3366            // The next app has not been requested to be visible, so we keep the current orientation
3367            // to prevent freezing/unfreezing the display too early.
3368            return mService.mLastOrientation;
3369        }
3370    }
3371
3372    /**
3373     * Window container class that contains all containers on this display that are not related to
3374     * Apps. E.g. status bar.
3375     */
3376    private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
3377        /**
3378         * Compares two child window tokens returns -1 if the first is lesser than the second in
3379         * terms of z-order and 1 otherwise.
3380         */
3381        final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
3382                // Tokens with higher base layer are z-ordered on-top.
3383                mService.mPolicy.windowTypeToLayerLw(token1.windowType)
3384                < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
3385
3386        private final String mName;
3387        NonAppWindowContainers(String name) {
3388            mName = name;
3389        }
3390
3391        void addChild(WindowToken token) {
3392            addChild(token, mWindowComparator);
3393        }
3394
3395        @Override
3396        String getName() {
3397            return mName;
3398        }
3399    }
3400}
3401