DisplayContent.java revision 7156b650f0d57522ebde67cebd201b339e08cf8e
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.WindowManager.DOCKED_BOTTOM;
33import static android.view.WindowManager.DOCKED_INVALID;
34import static android.view.WindowManager.DOCKED_TOP;
35import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
36import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
37import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
38import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
39import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
40import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
41import static android.view.WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
42import static android.view.WindowManager.LayoutParams.NEEDS_MENU_UNSET;
43import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
45import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
46import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
47import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
48import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
49import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
50import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
51import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
52import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
53import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
54import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS;
55import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
56import static android.view.WindowManagerPolicy.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
57import static com.android.server.wm.WindowAnimator.KEYGUARD_ANIMATING_OUT;
58import static com.android.server.wm.WindowAnimator.KEYGUARD_ANIM_TIMEOUT_MS;
59import static com.android.server.wm.WindowAnimator.KEYGUARD_NOT_SHOWN;
60import static com.android.server.wm.WindowAnimator.KEYGUARD_SHOWN;
61import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
62import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEYGUARD;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
74import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_MOVEMENT;
75import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
76import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
77import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
78import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
79import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
80import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
81import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
82import static com.android.server.wm.WindowManagerService.dipToPixel;
83import static com.android.server.wm.WindowManagerService.localLOGV;
84import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
85import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
86import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
87import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_BEFORE_ANIM;
88import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
89import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
90
91import android.annotation.NonNull;
92import android.app.ActivityManager.StackId;
93import android.content.res.Configuration;
94import android.graphics.Matrix;
95import android.graphics.Rect;
96import android.graphics.RectF;
97import android.graphics.Region;
98import android.graphics.Region.Op;
99import android.hardware.display.DisplayManagerInternal;
100import android.os.Debug;
101import android.os.Handler;
102import android.os.IBinder;
103import android.os.RemoteException;
104import android.os.SystemClock;
105import android.util.DisplayMetrics;
106import android.util.Slog;
107import android.view.Display;
108import android.view.DisplayInfo;
109import android.view.IWindow;
110import android.view.WindowManager;
111import android.view.WindowManagerPolicy;
112import android.view.animation.AlphaAnimation;
113import android.view.animation.Animation;
114
115import com.android.internal.util.FastPrintWriter;
116import com.android.internal.view.IInputMethodClient;
117
118import java.io.FileDescriptor;
119import java.io.PrintWriter;
120import java.io.StringWriter;
121import java.util.ArrayList;
122import java.util.Arrays;
123import java.util.Comparator;
124import java.util.HashMap;
125import java.util.Iterator;
126import java.util.List;
127
128/**
129 * Utility class for keeping track of the WindowStates and other pertinent contents of a
130 * particular Display.
131 *
132 * IMPORTANT: No method from this class should ever be used without holding
133 * WindowManagerService.mWindowMap.
134 */
135class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
136    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
137
138    /** Unique identifier of this stack. */
139    private final int mDisplayId;
140
141    // The display only has 2 child window containers. mTaskStackContainers which contains all
142    // window containers that are related to apps (Activities) and mNonAppWindowContainers which
143    // contains all window containers not related to apps (e.g. Status bar).
144    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
145    private final NonAppWindowContainers mNonAppWindowContainers = new NonAppWindowContainers();
146
147    /** Z-ordered (bottom-most first) list of all Window objects. Assigned to an element
148     * from mDisplayWindows; */
149    private final WindowList mWindows = new WindowList();
150
151    // Mapping from a token IBinder to a WindowToken object on this display.
152    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
153
154    int mInitialDisplayWidth = 0;
155    int mInitialDisplayHeight = 0;
156    int mInitialDisplayDensity = 0;
157    int mBaseDisplayWidth = 0;
158    int mBaseDisplayHeight = 0;
159    int mBaseDisplayDensity = 0;
160    boolean mDisplayScalingDisabled;
161    private final DisplayInfo mDisplayInfo = new DisplayInfo();
162    private final Display mDisplay;
163    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
164
165    Rect mBaseDisplayRect = new Rect();
166    private Rect mContentRect = new Rect();
167
168    // Accessed directly by all users.
169    private boolean mLayoutNeeded;
170    int pendingLayoutChanges;
171    final boolean isDefaultDisplay;
172
173    /** Window tokens that are in the process of exiting, but still on screen for animations. */
174    final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
175
176    /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
177     * (except a future lockscreen TaskStack) moves to the top. */
178    private TaskStack mHomeStack = null;
179
180    /** Detect user tapping outside of current focused task bounds .*/
181    TaskTapPointerEventListener mTapDetector;
182
183    /** Detect user tapping outside of current focused stack bounds .*/
184    private Region mTouchExcludeRegion = new Region();
185
186    /** Save allocating when calculating rects */
187    private final Rect mTmpRect = new Rect();
188    private final Rect mTmpRect2 = new Rect();
189    private final RectF mTmpRectF = new RectF();
190    private final Matrix mTmpMatrix = new Matrix();
191    private final Region mTmpRegion = new Region();
192
193    final WindowManagerService mService;
194
195    /** Remove this display when animation on it has completed. */
196    private boolean mDeferredRemoval;
197
198    final DockedStackDividerController mDividerControllerLocked;
199
200    final DimLayerController mDimLayerController;
201
202    final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
203
204    /** Used when rebuilding window list to keep track of windows that have been removed. */
205    private WindowState[] mRebuildTmp = new WindowState[20];
206
207    private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
208            new TaskForResizePointSearchResult();
209    private final GetWindowOnDisplaySearchResult mTmpGetWindowOnDisplaySearchResult =
210            new GetWindowOnDisplaySearchResult();
211
212    // True if this display is in the process of being removed. Used to determine if the removal of
213    // the display's direct children should be allowed.
214    private boolean mRemovingDisplay = false;
215
216    private final WindowLayersController mLayersController;
217    final WallpaperController mWallpaperController;
218    int mInputMethodAnimLayerAdjustment;
219
220    /**
221     * @param display May not be null.
222     * @param service You know.
223     * @param layersController window layer controller used to assign layer to the windows on this
224     *                         display.
225     * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
226     *                            wallpaper windows in the window list.
227     */
228    DisplayContent(Display display, WindowManagerService service,
229            WindowLayersController layersController, WallpaperController wallpaperController) {
230        mDisplay = display;
231        mDisplayId = display.getDisplayId();
232        mLayersController = layersController;
233        mWallpaperController = wallpaperController;
234        display.getDisplayInfo(mDisplayInfo);
235        display.getMetrics(mDisplayMetrics);
236        isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
237        mService = service;
238        initializeDisplayBaseInfo();
239        mDividerControllerLocked = new DockedStackDividerController(service, this);
240        mDimLayerController = new DimLayerController(this);
241
242        // These are the only direct children we should ever have and they are permanent.
243        super.addChild(mTaskStackContainers, null);
244        super.addChild(mNonAppWindowContainers, null);
245    }
246
247    int getDisplayId() {
248        return mDisplayId;
249    }
250
251    WindowList getWindowList() {
252        return mWindows;
253    }
254
255    WindowToken getWindowToken(IBinder binder) {
256        return mTokenMap.get(binder);
257    }
258
259    AppWindowToken getAppWindowToken(IBinder binder) {
260        final WindowToken token = getWindowToken(binder);
261        if (token == null) {
262            return null;
263        }
264        return token.asAppWindowToken();
265    }
266
267    void setWindowToken(IBinder binder, WindowToken token) {
268        final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
269        if (dc != null) {
270            // We currently don't support adding a window token to the display if the display
271            // already has the binder mapped to another token. If there is a use case for supporting
272            // this moving forward we will either need to merge the WindowTokens some how or have
273            // the binder map to a list of window tokens.
274            throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
275                    + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
276        }
277        mTokenMap.put(binder, token);
278
279        if (token.asAppWindowToken() == null) {
280            // Add non-app token to container hierarchy on the display. App tokens are added through
281            // the parent container managing them (e.g. Tasks).
282            mNonAppWindowContainers.addChild(token, null);
283        }
284    }
285
286    WindowToken removeWindowToken(IBinder binder) {
287        final WindowToken token = mTokenMap.remove(binder);
288        if (token != null && token.asAppWindowToken() == null) {
289            mNonAppWindowContainers.removeChild(token);
290        }
291        return token;
292    }
293
294    Display getDisplay() {
295        return mDisplay;
296    }
297
298    DisplayInfo getDisplayInfo() {
299        return mDisplayInfo;
300    }
301
302    DisplayMetrics getDisplayMetrics() {
303        return mDisplayMetrics;
304    }
305
306    DockedStackDividerController getDockedDividerController() {
307        return mDividerControllerLocked;
308    }
309
310    /**
311     * Returns true if the specified UID has access to this display.
312     */
313    boolean hasAccess(int uid) {
314        return mDisplay.hasAccess(uid);
315    }
316
317    boolean isPrivate() {
318        return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
319    }
320
321    TaskStack getHomeStack() {
322        if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
323            Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
324        }
325        return mHomeStack;
326    }
327
328    TaskStack getStackById(int stackId) {
329        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
330            final TaskStack stack = mTaskStackContainers.get(i);
331            if (stack.mStackId == stackId) {
332                return stack;
333            }
334        }
335        return null;
336    }
337
338    @Override
339    void onConfigurationChanged(Configuration newParentConfig) {
340        super.onConfigurationChanged(newParentConfig);
341
342        // The display size information is heavily dependent on the resources in the current
343        // configuration, so we need to reconfigure it every time the configuration changes.
344        // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
345        mService.reconfigureDisplayLocked(this);
346
347        getDockedDividerController().onConfigurationChanged();
348    }
349
350    /**
351     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
352     * bounds were updated.
353     */
354    void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
355        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
356            final TaskStack stack = mTaskStackContainers.get(i);
357            if (stack.updateBoundsAfterConfigChange()) {
358                changedStackList.add(stack.mStackId);
359            }
360        }
361    }
362
363    @Override
364    boolean fillsParent() {
365        return true;
366    }
367
368    @Override
369    boolean isVisible() {
370        return true;
371    }
372
373    @Override
374    void onAppTransitionDone() {
375        super.onAppTransitionDone();
376        rebuildAppWindowList();
377    }
378
379    @Override
380    int getOrientation() {
381        final WindowManagerPolicy policy = mService.mPolicy;
382
383        // TODO: All the logic before the last return statement in this method should really go in
384        // #NonAppWindowContainer.getOrientation() since it is trying to decide orientation based
385        // on non-app windows. But, we can not do that until the window list is always correct in
386        // terms of z-ordering based on layers.
387        if (mService.mDisplayFrozen) {
388            if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
389                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
390                        "Display is frozen, return " + mService.mLastWindowForcedOrientation);
391                // If the display is frozen, some activities may be in the middle of restarting, and
392                // thus have removed their old window. If the window has the flag to hide the lock
393                // screen, then the lock screen can re-appear and inflict its own orientation on us.
394                // Keep the orientation stable until this all settles down.
395                return mService.mLastWindowForcedOrientation;
396            } else if (policy.isKeyguardLocked()) {
397                // Use the last orientation the while the display is frozen with the keyguard
398                // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
399                // window. We don't want to check the show when locked window directly though as
400                // things aren't stable while the display is frozen, for example the window could be
401                // momentarily unavailable due to activity relaunch.
402                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
403                        + "return " + mService.mLastOrientation);
404                return mService.mLastOrientation;
405            }
406        } else {
407            for (int pos = mWindows.size() - 1; pos >= 0; --pos) {
408                final WindowState win = mWindows.get(pos);
409                if (win.mAppToken != null) {
410                    // We hit an application window. so the orientation will be determined by the
411                    // app window. No point in continuing further.
412                    break;
413                }
414                if (!win.isVisibleLw() || !win.mPolicyVisibilityAfterAnim) {
415                    continue;
416                }
417                int req = win.mAttrs.screenOrientation;
418                if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND) {
419                    continue;
420                }
421
422                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
423                if (policy.isKeyguardHostWindow(win.mAttrs)) {
424                    mService.mLastKeyguardForcedOrientation = req;
425                }
426                return (mService.mLastWindowForcedOrientation = req);
427            }
428            mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
429
430            if (policy.isKeyguardLocked()) {
431                // The screen is locked and no top system window is requesting an orientation.
432                // Return either the orientation of the show-when-locked app (if there is any) or
433                // the orientation of the keyguard. No point in searching from the rest of apps.
434                WindowState winShowWhenLocked = (WindowState) policy.getWinShowWhenLockedLw();
435                AppWindowToken appShowWhenLocked = winShowWhenLocked == null
436                        ? null : winShowWhenLocked.mAppToken;
437                if (appShowWhenLocked != null) {
438                    int req = appShowWhenLocked.getOrientation();
439                    if (req == SCREEN_ORIENTATION_BEHIND) {
440                        req = mService.mLastKeyguardForcedOrientation;
441                    }
442                    if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Done at " + appShowWhenLocked
443                            + " -- show when locked, return " + req);
444                    return req;
445                }
446                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
447                        "No one is requesting an orientation when the screen is locked");
448                return mService.mLastKeyguardForcedOrientation;
449            }
450        }
451
452        // Top system windows are not requesting an orientation. Start searching from apps.
453        return mTaskStackContainers.getOrientation();
454    }
455
456    void updateDisplayInfo() {
457        mDisplay.getDisplayInfo(mDisplayInfo);
458        mDisplay.getMetrics(mDisplayMetrics);
459        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
460            mTaskStackContainers.get(i).updateDisplayInfo(null);
461        }
462    }
463
464    void initializeDisplayBaseInfo() {
465        final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
466        if (displayManagerInternal != null) {
467            // Bootstrap the default logical display from the display manager.
468            final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
469            if (newDisplayInfo != null) {
470                mDisplayInfo.copyFrom(newDisplayInfo);
471            }
472        }
473
474        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
475        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
476        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
477        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
478    }
479
480    void getLogicalDisplayRect(Rect out) {
481        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
482        final int orientation = mDisplayInfo.rotation;
483        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
484        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
485        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
486        int width = mDisplayInfo.logicalWidth;
487        int left = (physWidth - width) / 2;
488        int height = mDisplayInfo.logicalHeight;
489        int top = (physHeight - height) / 2;
490        out.set(left, top, left + width, top + height);
491    }
492
493    private void getLogicalDisplayRect(Rect out, int orientation) {
494        getLogicalDisplayRect(out);
495
496        // Rotate the Rect if needed.
497        final int currentRotation = mDisplayInfo.rotation;
498        final int rotationDelta = deltaRotation(currentRotation, orientation);
499        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
500            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
501            mTmpRectF.set(out);
502            mTmpMatrix.mapRect(mTmpRectF);
503            mTmpRectF.round(out);
504        }
505    }
506
507    void getContentRect(Rect out) {
508        out.set(mContentRect);
509    }
510
511    /** Refer to {@link WindowManagerService#attachStack(int, int, boolean)} */
512    void attachStack(TaskStack stack, boolean onTop) {
513        mTaskStackContainers.attachStack(stack, onTop);
514    }
515
516    void moveStack(TaskStack stack, boolean toTop) {
517        mTaskStackContainers.moveStack(stack, toTop);
518    }
519
520    @Override
521    protected void addChild(DisplayChildWindowContainer child,
522            Comparator<DisplayChildWindowContainer> comparator) {
523        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
524    }
525
526    @Override
527    protected void addChild(DisplayChildWindowContainer child, int index) {
528        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
529    }
530
531    @Override
532    protected void removeChild(DisplayChildWindowContainer child) {
533        // Only allow removal of direct children from this display if the display is in the process
534        // of been removed.
535        if (mRemovingDisplay) {
536            super.removeChild(child);
537            return;
538        }
539        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
540    }
541
542    /**
543     * Propagate the new bounds to all child stacks.
544     * @param contentRect The bounds to apply at the top level.
545     */
546    void resize(Rect contentRect) {
547        mContentRect.set(contentRect);
548    }
549
550    int taskIdFromPoint(int x, int y) {
551        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
552            final TaskStack stack = mTaskStackContainers.get(stackNdx);
553            final int taskId = stack.taskIdFromPoint(x, y);
554            if (taskId != -1) {
555                return taskId;
556            }
557        }
558        return -1;
559    }
560
561    /**
562     * Find the task whose outside touch area (for resizing) (x, y) falls within.
563     * Returns null if the touch doesn't fall into a resizing area.
564     */
565    Task findTaskForResizePoint(int x, int y) {
566        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
567        mTmpTaskForResizePointSearchResult.reset();
568        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
569            final TaskStack stack = mTaskStackContainers.get(stackNdx);
570            if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
571                return null;
572            }
573
574            stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
575            if (mTmpTaskForResizePointSearchResult.searchDone) {
576                return mTmpTaskForResizePointSearchResult.taskForResize;
577            }
578        }
579        return null;
580    }
581
582    void setTouchExcludeRegion(Task focusedTask) {
583        mTouchExcludeRegion.set(mBaseDisplayRect);
584        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
585        mTmpRect2.setEmpty();
586        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
587            final TaskStack stack = mTaskStackContainers.get(stackNdx);
588            stack.setTouchExcludeRegion(
589                    focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
590        }
591        // If we removed the focused task above, add it back and only leave its
592        // outside touch area in the exclusion. TapDectector is not interested in
593        // any touch inside the focused task itself.
594        if (!mTmpRect2.isEmpty()) {
595            mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
596        }
597        final WindowState inputMethod = mService.mInputMethodWindow;
598        if (inputMethod != null && inputMethod.isVisibleLw()) {
599            // If the input method is visible and the user is typing, we don't want these touch
600            // events to be intercepted and used to change focus. This would likely cause a
601            // disappearance of the input method.
602            inputMethod.getTouchableRegion(mTmpRegion);
603            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
604        }
605        for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
606            WindowState win = mTapExcludedWindows.get(i);
607            win.getTouchableRegion(mTmpRegion);
608            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
609        }
610        if (getDockedStackVisibleForUserLocked() != null) {
611            mDividerControllerLocked.getTouchRegion(mTmpRect);
612            mTmpRegion.set(mTmpRect);
613            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
614        }
615        if (mTapDetector != null) {
616            mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
617        }
618    }
619
620    void switchUser() {
621        final WindowList windows = getWindowList();
622        for (int i = 0; i < windows.size(); i++) {
623            final WindowState win = windows.get(i);
624            if (win.isHiddenFromUserLocked()) {
625                if (DEBUG_VISIBILITY) Slog.w(TAG_WM, "user changing, hiding " + win
626                        + ", attrs=" + win.mAttrs.type + ", belonging to " + win.mOwnerUid);
627                win.hideLw(false);
628            }
629        }
630
631        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
632            mTaskStackContainers.get(stackNdx).switchUser();
633        }
634
635        rebuildAppWindowList();
636    }
637
638    void resetAnimationBackgroundAnimator() {
639        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
640            mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
641        }
642    }
643
644    boolean animateDimLayers() {
645        return mDimLayerController.animateDimLayers();
646    }
647
648    void resetDimming() {
649        mDimLayerController.resetDimming();
650    }
651
652    boolean isDimming() {
653        return mDimLayerController.isDimming();
654    }
655
656    void stopDimmingIfNeeded() {
657        mDimLayerController.stopDimmingIfNeeded();
658    }
659
660    @Override
661    void removeIfPossible() {
662        if (isAnimating()) {
663            mDeferredRemoval = true;
664            return;
665        }
666        removeImmediately();
667    }
668
669    @Override
670    void removeImmediately() {
671        mRemovingDisplay = true;
672        try {
673            super.removeImmediately();
674            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
675            mDimLayerController.close();
676            if (mDisplayId == DEFAULT_DISPLAY) {
677                mService.unregisterPointerEventListener(mTapDetector);
678                mService.unregisterPointerEventListener(mService.mMousePositionTracker);
679            }
680        } finally {
681            mRemovingDisplay = false;
682        }
683    }
684
685    /** Returns true if a removal action is still being deferred. */
686    @Override
687    boolean checkCompleteDeferredRemoval() {
688        final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
689
690        if (!stillDeferringRemoval && mDeferredRemoval) {
691            removeImmediately();
692            mService.onDisplayRemoved(mDisplayId);
693            return false;
694        }
695        return true;
696    }
697
698    boolean animateForIme(float interpolatedValue, float animationTarget,
699            float dividerAnimationTarget) {
700        boolean updated = false;
701
702        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
703            final TaskStack stack = mTaskStackContainers.get(i);
704            if (stack == null || !stack.isAdjustedForIme()) {
705                continue;
706            }
707
708            if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
709                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
710                updated = true;
711            } else {
712                mDividerControllerLocked.mLastAnimationProgress =
713                        mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
714                mDividerControllerLocked.mLastDividerProgress =
715                        mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
716                updated |= stack.updateAdjustForIme(
717                        mDividerControllerLocked.mLastAnimationProgress,
718                        mDividerControllerLocked.mLastDividerProgress,
719                        false /* force */);
720            }
721            if (interpolatedValue >= 1f) {
722                stack.endImeAdjustAnimation();
723            }
724        }
725
726        return updated;
727    }
728
729    boolean clearImeAdjustAnimation() {
730        boolean changed = false;
731        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
732            final TaskStack stack = mTaskStackContainers.get(i);
733            if (stack != null && stack.isAdjustedForIme()) {
734                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
735                changed  = true;
736            }
737        }
738        return changed;
739    }
740
741    void beginImeAdjustAnimation() {
742        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
743            final TaskStack stack = mTaskStackContainers.get(i);
744            if (stack.isVisible() && stack.isAdjustedForIme()) {
745                stack.beginImeAdjustAnimation();
746            }
747        }
748    }
749
750    void adjustForImeIfNeeded() {
751        final WindowState imeWin = mService.mInputMethodWindow;
752        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
753                && !mDividerControllerLocked.isImeHideRequested();
754        final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
755        final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
756        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
757                imeTargetStack.getDockSide() : DOCKED_INVALID;
758        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
759        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
760        final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
761        final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
762        final boolean imeHeightChanged = imeVisible &&
763                imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
764
765        // The divider could be adjusted for IME position, or be thinner than usual,
766        // or both. There are three possible cases:
767        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
768        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
769        // - If IME is not visible, divider is not moved and is normal width.
770
771        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
772            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
773                final TaskStack stack = mTaskStackContainers.get(i);
774                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
775                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
776                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
777                } else {
778                    stack.resetAdjustedForIme(false);
779                }
780            }
781            mDividerControllerLocked.setAdjustedForIme(
782                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
783        } else {
784            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
785                final TaskStack stack = mTaskStackContainers.get(i);
786                stack.resetAdjustedForIme(!dockVisible);
787            }
788            mDividerControllerLocked.setAdjustedForIme(
789                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
790        }
791    }
792
793    void setInputMethodAnimLayerAdjustment(int adj) {
794        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
795        mInputMethodAnimLayerAdjustment = adj;
796        final WindowState imw = mService.mInputMethodWindow;
797        if (imw != null) {
798            imw.adjustAnimLayer(adj);
799        }
800        for (int i = mService.mInputMethodDialogs.size() - 1; i >= 0; i--) {
801            final WindowState dialog = mService.mInputMethodDialogs.get(i);
802            // TODO: This and other places setting mAnimLayer can probably use WS.adjustAnimLayer,
803            // but need to make sure we are not setting things twice for child windows that are
804            // already in the list.
805            dialog.mWinAnimator.mAnimLayer = dialog.mLayer + adj;
806            if (DEBUG_LAYERS) Slog.v(TAG_WM, "IM win " + imw
807                    + " anim layer: " + dialog.mWinAnimator.mAnimLayer);
808        }
809    }
810
811    /**
812     * If a window that has an animation specifying a colored background and the current wallpaper
813     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
814     * suddenly disappear.
815     */
816    int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
817        for (int i = mWindows.size() - 1; i >= 0; --i) {
818            final WindowState win = mWindows.get(i);
819            if (win.mIsWallpaper && win.isVisibleNow()) {
820                return win.mWinAnimator.mAnimLayer;
821            }
822        }
823        return winAnimator.mAnimLayer;
824    }
825
826    void prepareFreezingTaskBounds() {
827        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
828            final TaskStack stack = mTaskStackContainers.get(stackNdx);
829            stack.prepareFreezingTaskBounds();
830        }
831    }
832
833    void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
834        getLogicalDisplayRect(mTmpRect, newRotation);
835
836        // Compute a transform matrix to undo the coordinate space transformation,
837        // and present the window at the same physical position it previously occupied.
838        final int deltaRotation = deltaRotation(newRotation, oldRotation);
839        createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
840
841        mTmpRectF.set(bounds);
842        mTmpMatrix.mapRect(mTmpRectF);
843        mTmpRectF.round(bounds);
844    }
845
846    static int deltaRotation(int oldRotation, int newRotation) {
847        int delta = newRotation - oldRotation;
848        if (delta < 0) delta += 4;
849        return delta;
850    }
851
852    private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
853            Matrix outMatrix) {
854        // For rotations without Z-ordering we don't need the target rectangle's position.
855        createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
856                displayHeight, outMatrix);
857    }
858
859    static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
860            float displayWidth, float displayHeight, Matrix outMatrix) {
861        switch (rotation) {
862            case ROTATION_0:
863                outMatrix.reset();
864                break;
865            case ROTATION_270:
866                outMatrix.setRotate(270, 0, 0);
867                outMatrix.postTranslate(0, displayHeight);
868                outMatrix.postTranslate(rectTop, 0);
869                break;
870            case ROTATION_180:
871                outMatrix.reset();
872                break;
873            case ROTATION_90:
874                outMatrix.setRotate(90, 0, 0);
875                outMatrix.postTranslate(displayWidth, 0);
876                outMatrix.postTranslate(-rectTop, rectLeft);
877                break;
878        }
879    }
880
881    public void dump(String prefix, PrintWriter pw) {
882        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
883        final String subPrefix = "  " + prefix;
884        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
885            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
886            pw.print("dpi");
887            if (mInitialDisplayWidth != mBaseDisplayWidth
888                    || mInitialDisplayHeight != mBaseDisplayHeight
889                    || mInitialDisplayDensity != mBaseDisplayDensity) {
890                pw.print(" base=");
891                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
892                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
893            }
894            if (mDisplayScalingDisabled) {
895                pw.println(" noscale");
896            }
897            pw.print(" cur=");
898            pw.print(mDisplayInfo.logicalWidth);
899            pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
900            pw.print(" app=");
901            pw.print(mDisplayInfo.appWidth);
902            pw.print("x"); pw.print(mDisplayInfo.appHeight);
903            pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
904            pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
905            pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
906            pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
907            pw.println(subPrefix + "deferred=" + mDeferredRemoval
908                    + " mLayoutNeeded=" + mLayoutNeeded);
909
910        pw.println();
911        pw.println("  Application tokens in top down Z order:");
912        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
913            final TaskStack stack = mTaskStackContainers.get(stackNdx);
914            stack.dump(prefix + "  ", pw);
915        }
916
917        pw.println();
918        if (!mExitingTokens.isEmpty()) {
919            pw.println();
920            pw.println("  Exiting tokens:");
921            for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
922                final WindowToken token = mExitingTokens.get(i);
923                pw.print("  Exiting #"); pw.print(i);
924                pw.print(' '); pw.print(token);
925                pw.println(':');
926                token.dump(pw, "    ");
927            }
928        }
929        pw.println();
930        mDimLayerController.dump(prefix + "  ", pw);
931        pw.println();
932        mDividerControllerLocked.dump(prefix + "  ", pw);
933
934        if (mInputMethodAnimLayerAdjustment != 0) {
935            pw.println(subPrefix
936                    + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment);
937        }
938    }
939
940    @Override
941    public String toString() {
942        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
943    }
944
945    String getName() {
946        return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
947    }
948
949    /**
950     * @return The docked stack, but only if it is visible, and {@code null} otherwise.
951     */
952    TaskStack getDockedStackLocked() {
953        final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
954        return (stack != null && stack.isVisible()) ? stack : null;
955    }
956
957    /**
958     * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
959     * visible, as long as it's not hidden because the current user doesn't have any tasks there.
960     */
961    TaskStack getDockedStackVisibleForUserLocked() {
962        final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
963        return (stack != null && stack.isVisible(true /* ignoreKeyguard */)) ? stack : null;
964    }
965
966    /** Find the visible, touch-deliverable window under the given point */
967    WindowState getTouchableWinAtPointLocked(float xf, float yf) {
968        WindowState touchedWin = null;
969        final int x = (int) xf;
970        final int y = (int) yf;
971
972        for (int i = mWindows.size() - 1; i >= 0; i--) {
973            WindowState window = mWindows.get(i);
974            final int flags = window.mAttrs.flags;
975            if (!window.isVisibleLw()) {
976                continue;
977            }
978            if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
979                continue;
980            }
981
982            window.getVisibleBounds(mTmpRect);
983            if (!mTmpRect.contains(x, y)) {
984                continue;
985            }
986
987            window.getTouchableRegion(mTmpRegion);
988
989            final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
990            if (mTmpRegion.contains(x, y) || touchFlags == 0) {
991                touchedWin = window;
992                break;
993            }
994        }
995
996        return touchedWin;
997    }
998
999    boolean canAddToastWindowForUid(int uid) {
1000        // We allow one toast window per UID being shown at a time.
1001        WindowList windows = getWindowList();
1002        final int windowCount = windows.size();
1003        for (int i = 0; i < windowCount; i++) {
1004            WindowState window = windows.get(i);
1005            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == uid
1006                    && !window.mPermanentlyHidden && !window.mAnimatingExit
1007                    && !window.mRemoveOnExit) {
1008                return false;
1009            }
1010        }
1011        return true;
1012    }
1013
1014    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
1015        if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
1016            return;
1017        }
1018        final int lostFocusUid = oldFocus.mOwnerUid;
1019        final WindowList windows = getWindowList();
1020        final int windowCount = windows.size();
1021        final Handler handler = mService.mH;
1022        for (int i = 0; i < windowCount; i++) {
1023            final WindowState window = windows.get(i);
1024            if (window.mAttrs.type == TYPE_TOAST && window.mOwnerUid == lostFocusUid) {
1025                if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, window)) {
1026                    handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, window),
1027                            window.mAttrs.hideTimeoutMilliseconds);
1028                }
1029            }
1030        }
1031    }
1032
1033    WindowState findFocusedWindow() {
1034        final AppWindowToken focusedApp = mService.mFocusedApp;
1035
1036        for (int i = mWindows.size() - 1; i >= 0; i--) {
1037            final WindowState win = mWindows.get(i);
1038
1039            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + i + " = " + win
1040                    + ", flags=" + win.mAttrs.flags + ", canReceive=" + win.canReceiveKeys());
1041
1042            if (!win.canReceiveKeys()) {
1043                continue;
1044            }
1045
1046            final AppWindowToken wtoken = win.mAppToken;
1047
1048            // If this window's application has been removed, just skip it.
1049            if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
1050                if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
1051                        + (wtoken.removed ? "removed" : "sendingToBottom"));
1052                continue;
1053            }
1054
1055            if (focusedApp == null) {
1056                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
1057                        + " using new focus @ " + i + " = " + win);
1058                return win;
1059            }
1060
1061            if (!focusedApp.windowsAreFocusable()) {
1062                // Current focused app windows aren't focusable...
1063                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
1064                        + " focusable using new focus @ " + i + " = " + win);
1065                return win;
1066            }
1067
1068            // Descend through all of the app tokens and find the first that either matches
1069            // win.mAppToken (return win) or mFocusedApp (return null).
1070            if (wtoken != null && win.mAttrs.type != TYPE_APPLICATION_STARTING) {
1071                if (focusedApp.compareTo(wtoken) > 0) {
1072                    // App stack below focused app stack. No focus for you!!!
1073                    if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
1074                            "findFocusedWindow: Reached focused app=" + focusedApp);
1075                    return null;
1076                }
1077            }
1078
1079            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ "
1080                    + i + " = " + win);
1081            return win;
1082        }
1083
1084        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
1085        return null;
1086    }
1087
1088    int addAppWindowToWindowList(final WindowState win) {
1089        final IWindow client = win.mClient;
1090
1091        WindowList tokenWindowList = getTokenWindowsOnDisplay(win.mToken);
1092        if (!tokenWindowList.isEmpty()) {
1093            return addAppWindowExisting(win, tokenWindowList);
1094        }
1095
1096        // No windows from this token on this display
1097        if (localLOGV) Slog.v(TAG_WM, "Figuring out where to add app window "
1098                + client.asBinder() + " (token=" + this + ")");
1099
1100        final WindowToken wToken = win.mToken;
1101
1102        // Figure out where the window should go, based on the order of applications.
1103        mTmpGetWindowOnDisplaySearchResult.reset();
1104        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1105            final TaskStack stack = mTaskStackContainers.get(i);
1106            stack.getWindowOnDisplayBeforeToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1107            if (mTmpGetWindowOnDisplaySearchResult.reachedToken) {
1108                // We have reach the token we are interested in. End search.
1109                break;
1110            }
1111        }
1112
1113        WindowState pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
1114
1115        // We now know the index into the apps. If we found an app window above, that gives us the
1116        // position; else we need to look some more.
1117        if (pos != null) {
1118            // Move behind any windows attached to this one.
1119            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
1120            if (atoken != null) {
1121                tokenWindowList = getTokenWindowsOnDisplay(atoken);
1122                final int NC = tokenWindowList.size();
1123                if (NC > 0) {
1124                    WindowState bottom = tokenWindowList.get(0);
1125                    if (bottom.mSubLayer < 0) {
1126                        pos = bottom;
1127                    }
1128                }
1129            }
1130            addWindowToListBefore(win, pos);
1131            return 0;
1132        }
1133
1134        // Continue looking down until we find the first token that has windows on this display.
1135        mTmpGetWindowOnDisplaySearchResult.reset();
1136        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1137            final TaskStack stack = mTaskStackContainers.get(i);
1138            stack.getWindowOnDisplayAfterToken(this, wToken, mTmpGetWindowOnDisplaySearchResult);
1139            if (mTmpGetWindowOnDisplaySearchResult.foundWindow != null) {
1140                // We have found a window after the token. End search.
1141                break;
1142            }
1143        }
1144
1145        pos = mTmpGetWindowOnDisplaySearchResult.foundWindow;
1146
1147        if (pos != null) {
1148            // Move in front of any windows attached to this one.
1149            final WindowToken atoken = getWindowToken(pos.mClient.asBinder());
1150            if (atoken != null) {
1151                final WindowState top = atoken.getTopWindow();
1152                if (top != null && top.mSubLayer >= 0) {
1153                    pos = top;
1154                }
1155            }
1156            addWindowToListAfter(win, pos);
1157            return 0;
1158        }
1159
1160        // Just search for the start of this layer.
1161        final int myLayer = win.mBaseLayer;
1162        int i;
1163        for (i = mWindows.size() - 1; i >= 0; --i) {
1164            final WindowState w = mWindows.get(i);
1165            // Dock divider shares the base layer with application windows, but we want to always
1166            // keep it above the application windows. The sharing of the base layer is intended
1167            // for window animations, which need to be above the dock divider for the duration
1168            // of the animation.
1169            if (w.mBaseLayer <= myLayer && w.mAttrs.type != TYPE_DOCK_DIVIDER) {
1170                break;
1171            }
1172        }
1173        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1174                "Based on layer: Adding window " + win + " at " + (i + 1) + " of "
1175                + mWindows.size());
1176        mWindows.add(i + 1, win);
1177        mService.mWindowsChanged = true;
1178        return 0;
1179    }
1180
1181    /** Adds this non-app window to the window list. */
1182    void addNonAppWindowToWindowList(WindowState win) {
1183        // Figure out where window should go, based on layer.
1184        int i;
1185        for (i = mWindows.size() - 1; i >= 0; i--) {
1186            final WindowState otherWin = mWindows.get(i);
1187            if (otherWin.getBaseType() != TYPE_WALLPAPER && otherWin.mBaseLayer <= win.mBaseLayer) {
1188                // Wallpaper wanders through the window list, for example to position itself
1189                // directly behind keyguard. Because of this it will break the ordering based on
1190                // WindowState.mBaseLayer. There might windows with higher mBaseLayer behind it and
1191                // we don't want the new window to appear above them. An example of this is adding
1192                // of the docked stack divider. Consider a scenario with the following ordering (top
1193                // to bottom): keyguard, wallpaper, assist preview, apps. We want the dock divider
1194                // to land below the assist preview, so the dock divider must ignore the wallpaper,
1195                // with which it shares the base layer.
1196                break;
1197            }
1198        }
1199
1200        i++;
1201        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1202                "Free window: Adding window " + this + " at " + i + " of " + mWindows.size());
1203        mWindows.add(i, win);
1204        mService.mWindowsChanged = true;
1205    }
1206
1207    void addToWindowList(WindowState win, int index) {
1208        mWindows.add(index, win);
1209    }
1210
1211    boolean removeFromWindowList(WindowState win) {
1212        return mWindows.remove(win);
1213    }
1214
1215    private int removeWindowAndChildrenFromWindowList(WindowState win, int interestingPos) {
1216        final WindowList windows = getWindowList();
1217        int wpos = windows.indexOf(win);
1218        if (wpos < 0) {
1219            return interestingPos;
1220        }
1221
1222        if (wpos < interestingPos) interestingPos--;
1223        if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Temp removing at " + wpos + ": " + this);
1224        windows.remove(wpos);
1225        mService.mWindowsChanged = true;
1226        int childWinCount = win.mChildren.size();
1227        while (childWinCount > 0) {
1228            childWinCount--;
1229            final WindowState cw = win.mChildren.get(childWinCount);
1230            int cpos = windows.indexOf(cw);
1231            if (cpos >= 0) {
1232                if (cpos < interestingPos) interestingPos--;
1233                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM,
1234                        "Temp removing child at " + cpos + ": " + cw);
1235                windows.remove(cpos);
1236            }
1237        }
1238        return interestingPos;
1239    }
1240
1241    void addChildWindowToWindowList(WindowState win) {
1242        final WindowState parentWindow = win.getParentWindow();
1243
1244        WindowList windowsOnSameDisplay = getTokenWindowsOnDisplay(win.mToken);
1245
1246        // Figure out this window's ordering relative to the parent window.
1247        final int wCount = windowsOnSameDisplay.size();
1248        final int sublayer = win.mSubLayer;
1249        int largestSublayer = Integer.MIN_VALUE;
1250        WindowState windowWithLargestSublayer = null;
1251        int i;
1252        for (i = 0; i < wCount; i++) {
1253            WindowState w = windowsOnSameDisplay.get(i);
1254            final int wSublayer = w.mSubLayer;
1255            if (wSublayer >= largestSublayer) {
1256                largestSublayer = wSublayer;
1257                windowWithLargestSublayer = w;
1258            }
1259            if (sublayer < 0) {
1260                // For negative sublayers, we go below all windows in the same sublayer.
1261                if (wSublayer >= sublayer) {
1262                    addWindowToListBefore(win, wSublayer >= 0 ? parentWindow : w);
1263                    break;
1264                }
1265            } else {
1266                // For positive sublayers, we go above all windows in the same sublayer.
1267                if (wSublayer > sublayer) {
1268                    addWindowToListBefore(win, w);
1269                    break;
1270                }
1271            }
1272        }
1273        if (i >= wCount) {
1274            if (sublayer < 0) {
1275                addWindowToListBefore(win, parentWindow);
1276            } else {
1277                addWindowToListAfter(win,
1278                        largestSublayer >= 0 ? windowWithLargestSublayer : parentWindow);
1279            }
1280        }
1281    }
1282
1283    /** Updates the layer assignment of windows on this display. */
1284    void assignWindowLayers(boolean setLayoutNeeded) {
1285        mLayersController.assignWindowLayers(mWindows);
1286        if (setLayoutNeeded) {
1287            setLayoutNeeded();
1288        }
1289    }
1290
1291    void adjustWallpaperWindows() {
1292        if (mWallpaperController.adjustWallpaperWindows(mWindows)) {
1293            assignWindowLayers(true /*setLayoutNeeded*/);
1294        }
1295    }
1296
1297    /**
1298     * Z-orders the display window list so that:
1299     * <ul>
1300     * <li>Any windows that are currently below the wallpaper window stay below the wallpaper
1301     *      window.
1302     * <li>Exiting application windows are at the bottom, but above the wallpaper window.
1303     * <li>All other application windows are above the exiting application windows and ordered based
1304     *      on the ordering of their stacks and tasks on the display.
1305     * <li>Non-application windows are at the very top.
1306     * </ul>
1307     * <p>
1308     * NOTE: This isn't a complete picture of what the user see. Further manipulation of the window
1309     *       surface layering is done in {@link WindowLayersController}.
1310     */
1311    void rebuildAppWindowList() {
1312        int count = mWindows.size();
1313        int i;
1314        int lastBelow = -1;
1315        int numRemoved = 0;
1316
1317        if (mRebuildTmp.length < count) {
1318            mRebuildTmp = new WindowState[count + 10];
1319        }
1320
1321        // First remove all existing app windows.
1322        i = 0;
1323        while (i < count) {
1324            final WindowState w = mWindows.get(i);
1325            if (w.mAppToken != null) {
1326                final WindowState win = mWindows.remove(i);
1327                win.mRebuilding = true;
1328                mRebuildTmp[numRemoved] = win;
1329                mService.mWindowsChanged = true;
1330                if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "Rebuild removing window: " + win);
1331                count--;
1332                numRemoved++;
1333                continue;
1334            } else if (lastBelow == i-1) {
1335                if (w.mAttrs.type == TYPE_WALLPAPER) {
1336                    lastBelow = i;
1337                }
1338            }
1339            i++;
1340        }
1341
1342        // Keep whatever windows were below the app windows still below, by skipping them.
1343        lastBelow++;
1344        i = lastBelow;
1345
1346        // First add all of the exiting app tokens...  these are no longer in the main app list,
1347        // but still have windows shown. We put them in the back because now that the animation is
1348        // over we no longer will care about them.
1349        final int numStacks = mTaskStackContainers.size();
1350        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1351            AppTokenList exitingAppTokens = mTaskStackContainers.get(stackNdx).mExitingAppTokens;
1352            int NT = exitingAppTokens.size();
1353            for (int j = 0; j < NT; j++) {
1354                i = exitingAppTokens.get(j).rebuildWindowListUnchecked(i);
1355            }
1356        }
1357
1358        // And add in the still active app tokens in Z order.
1359        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1360            i = mTaskStackContainers.get(stackNdx).rebuildWindowList(i);
1361        }
1362
1363        i -= lastBelow;
1364        if (i != numRemoved) {
1365            setLayoutNeeded();
1366            Slog.w(TAG_WM, "On display=" + mDisplayId + " Rebuild removed " + numRemoved
1367                    + " windows but added " + i + " rebuildAppWindowListLocked() "
1368                    + " callers=" + Debug.getCallers(10));
1369            for (i = 0; i < numRemoved; i++) {
1370                WindowState ws = mRebuildTmp[i];
1371                if (ws.mRebuilding) {
1372                    StringWriter sw = new StringWriter();
1373                    PrintWriter pw = new FastPrintWriter(sw, false, 1024);
1374                    ws.dump(pw, "", true);
1375                    pw.flush();
1376                    Slog.w(TAG_WM, "This window was lost: " + ws);
1377                    Slog.w(TAG_WM, sw.toString());
1378                    ws.mWinAnimator.destroySurfaceLocked();
1379                }
1380            }
1381            Slog.w(TAG_WM, "Current window hierarchy:");
1382            dumpChildrenNames();
1383            Slog.w(TAG_WM, "Final window list:");
1384            dumpWindows();
1385        }
1386        Arrays.fill(mRebuildTmp, null);
1387    }
1388
1389    /** Return the list of Windows on this display associated with the input token. */
1390    WindowList getTokenWindowsOnDisplay(WindowToken token) {
1391        final WindowList windowList = new WindowList();
1392        final int count = mWindows.size();
1393        for (int i = 0; i < count; i++) {
1394            final WindowState win = mWindows.get(i);
1395            if (win.mToken == token) {
1396                windowList.add(win);
1397            }
1398        }
1399        return windowList;
1400    }
1401
1402    private void reAddToWindowList(WindowState win) {
1403        win.mToken.addWindow(win);
1404        // This is a hack to get all of the child windows added as well at the right position. Child
1405        // windows should be rare and this case should be rare, so it shouldn't be that big a deal.
1406        int wpos = mWindows.indexOf(win);
1407        if (wpos >= 0) {
1408            if (DEBUG_WINDOW_MOVEMENT) Slog.v(TAG_WM, "ReAdd removing from " + wpos + ": " + win);
1409            mWindows.remove(wpos);
1410            mService.mWindowsChanged = true;
1411            win.reAddWindow(wpos);
1412        }
1413    }
1414
1415    void moveInputMethodDialogs(int pos) {
1416        ArrayList<WindowState> dialogs = mService.mInputMethodDialogs;
1417
1418        final int N = dialogs.size();
1419        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Removing " + N + " dialogs w/pos=" + pos);
1420        for (int i = 0; i < N; i++) {
1421            pos = removeWindowAndChildrenFromWindowList(dialogs.get(i), pos);
1422        }
1423        if (DEBUG_INPUT_METHOD) {
1424            Slog.v(TAG_WM, "Window list w/pos=" + pos);
1425            logWindowList(mWindows, "  ");
1426        }
1427
1428        WindowState ime = mService.mInputMethodWindow;
1429        if (pos >= 0) {
1430            // Skip windows owned by the input method.
1431            if (ime != null) {
1432                while (pos < mWindows.size()) {
1433                    WindowState wp = mWindows.get(pos);
1434                    if (wp == ime || wp.getParentWindow() == ime) {
1435                        pos++;
1436                        continue;
1437                    }
1438                    break;
1439                }
1440            }
1441            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Adding " + N + " dialogs at pos=" + pos);
1442            for (int i=0; i<N; i++) {
1443                WindowState win = dialogs.get(i);
1444                pos = win.reAddWindow(pos);
1445            }
1446            if (DEBUG_INPUT_METHOD) {
1447                Slog.v(TAG_WM, "Final window list:");
1448                logWindowList(mWindows, "  ");
1449            }
1450            return;
1451        }
1452        for (int i=0; i<N; i++) {
1453            WindowState win = dialogs.get(i);
1454            reAddToWindowList(win);
1455            if (DEBUG_INPUT_METHOD) {
1456                Slog.v(TAG_WM, "No IM target, final list:");
1457                logWindowList(mWindows, "  ");
1458            }
1459        }
1460    }
1461
1462    boolean moveInputMethodWindowsIfNeeded(boolean needAssignLayers) {
1463        final WindowState imWin = mService.mInputMethodWindow;
1464        final int DN = mService.mInputMethodDialogs.size();
1465        if (imWin == null && DN == 0) {
1466            return false;
1467        }
1468
1469        // TODO(multidisplay): IMEs are only supported on the default display.
1470        WindowList windows = mWindows;
1471
1472        int imPos = findDesiredInputMethodWindowIndex(true);
1473        if (imPos >= 0) {
1474            // In this case, the input method windows are to be placed
1475            // immediately above the window they are targeting.
1476
1477            // First check to see if the input method windows are already
1478            // located here, and contiguous.
1479            final int N = windows.size();
1480            final WindowState firstImWin = imPos < N ? windows.get(imPos) : null;
1481
1482            // Figure out the actual input method window that should be
1483            // at the bottom of their stack.
1484            WindowState baseImWin = imWin != null ? imWin : mService.mInputMethodDialogs.get(0);
1485            final WindowState cw = baseImWin.getBottomChild();
1486            if (cw != null && cw.mSubLayer < 0) {
1487                baseImWin = cw;
1488            }
1489
1490            if (firstImWin == baseImWin) {
1491                // The windows haven't moved...  but are they still contiguous?
1492                // First find the top IM window.
1493                int pos = imPos+1;
1494                while (pos < N) {
1495                    if (!(windows.get(pos)).mIsImWindow) {
1496                        break;
1497                    }
1498                    pos++;
1499                }
1500                pos++;
1501                // Now there should be no more input method windows above.
1502                while (pos < N) {
1503                    if ((windows.get(pos)).mIsImWindow) {
1504                        break;
1505                    }
1506                    pos++;
1507                }
1508                if (pos >= N) {
1509                    return false;
1510                }
1511            }
1512
1513            if (imWin != null) {
1514                if (DEBUG_INPUT_METHOD) {
1515                    Slog.v(TAG_WM, "Moving IM from " + imPos);
1516                    logWindowList(windows, "  ");
1517                }
1518                imPos = removeWindowAndChildrenFromWindowList(imWin, imPos);
1519                if (DEBUG_INPUT_METHOD) {
1520                    Slog.v(TAG_WM, "List after removing with new pos " + imPos + ":");
1521                    logWindowList(windows, "  ");
1522                }
1523                imWin.reAddWindow(imPos);
1524                if (DEBUG_INPUT_METHOD) {
1525                    Slog.v(TAG_WM, "List after moving IM to " + imPos + ":");
1526                    logWindowList(windows, "  ");
1527                }
1528                if (DN > 0) moveInputMethodDialogs(imPos+1);
1529            } else {
1530                moveInputMethodDialogs(imPos);
1531            }
1532
1533        } else {
1534            // In this case, the input method windows go in a fixed layer,
1535            // because they aren't currently associated with a focus window.
1536
1537            if (imWin != null) {
1538                if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Moving IM from " + imPos);
1539                removeWindowAndChildrenFromWindowList(imWin, 0);
1540                reAddToWindowList(imWin);
1541                if (DEBUG_INPUT_METHOD) {
1542                    Slog.v(TAG_WM, "List with no IM target:");
1543                    logWindowList(windows, "  ");
1544                }
1545                if (DN > 0) moveInputMethodDialogs(-1);
1546            } else {
1547                moveInputMethodDialogs(-1);
1548            }
1549
1550        }
1551
1552        if (needAssignLayers) {
1553            assignWindowLayers(false /* setLayoutNeeded */);
1554        }
1555
1556        return true;
1557    }
1558
1559    /**
1560     * Dig through the WindowStates and find the one that the Input Method will target.
1561     * @param willMove
1562     * @return The index+1 in mWindows of the discovered target.
1563     */
1564    int findDesiredInputMethodWindowIndex(boolean willMove) {
1565        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1566        // same display. Or even when the current IME/target are not on the same screen as the next
1567        // IME/target. For now only look for input windows on the main screen.
1568        final WindowList windows = getWindowList();
1569        WindowState w = null;
1570        int i;
1571        for (i = windows.size() - 1; i >= 0; --i) {
1572            WindowState win = windows.get(i);
1573
1574            if (DEBUG_INPUT_METHOD && willMove) Slog.i(TAG_WM, "Checking window @" + i
1575                    + " " + win + " fl=0x" + Integer.toHexString(win.mAttrs.flags));
1576            if (canBeImeTarget(win)) {
1577                w = win;
1578                //Slog.i(TAG_WM, "Putting input method here!");
1579
1580                // Yet more tricksyness!  If this window is a "starting" window, we do actually want
1581                // to be on top of it, but it is not -really- where input will go.  So if the caller
1582                // is not actually looking to move the IME, look down below for a real window to
1583                // target...
1584                if (!willMove && w.mAttrs.type == TYPE_APPLICATION_STARTING && i > 0) {
1585                    WindowState wb = windows.get(i-1);
1586                    if (wb.mAppToken == w.mAppToken && canBeImeTarget(wb)) {
1587                        i--;
1588                        w = wb;
1589                    }
1590                }
1591                break;
1592            }
1593        }
1594
1595        // Now w is either mWindows[0] or an IME (or null if mWindows is empty).
1596
1597        if (DEBUG_INPUT_METHOD && willMove) Slog.v(TAG_WM, "Proposed new IME target: " + w);
1598
1599        // Now, a special case -- if the last target's window is in the process of exiting, and is
1600        // above the new target, keep on the last target to avoid flicker. Consider for example a
1601        // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
1602        // until it is completely gone so it doesn't drop behind the dialog or its full-screen
1603        // scrim.
1604        final WindowState curTarget = mService.mInputMethodTarget;
1605        if (curTarget != null
1606                && curTarget.isDisplayedLw()
1607                && curTarget.isClosing()
1608                && (w == null || curTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer)) {
1609            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
1610            return windows.indexOf(curTarget) + 1;
1611        }
1612
1613        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target="
1614                + w + " willMove=" + willMove);
1615
1616        if (willMove && w != null) {
1617            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1618            if (token != null) {
1619
1620                // Now some fun for dealing with window animations that modify the Z order. We need
1621                // to look at all windows below the current target that are in this app, finding the
1622                // highest visible one in layering.
1623                WindowState highestTarget = null;
1624                int highestPos = 0;
1625                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1626                    WindowList curWindows = token.getDisplayContent().getWindowList();
1627                    int pos = curWindows.indexOf(curTarget);
1628                    while (pos >= 0) {
1629                        WindowState win = curWindows.get(pos);
1630                        if (win.mAppToken != token) {
1631                            break;
1632                        }
1633                        if (!win.mRemoved) {
1634                            if (highestTarget == null || win.mWinAnimator.mAnimLayer >
1635                                    highestTarget.mWinAnimator.mAnimLayer) {
1636                                highestTarget = win;
1637                                highestPos = pos;
1638                            }
1639                        }
1640                        pos--;
1641                    }
1642                }
1643
1644                if (highestTarget != null) {
1645                    final AppTransition appTransition = mService.mAppTransition;
1646                    if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
1647                            + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1648                            + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1649                            + " new layer=" + w.mWinAnimator.mAnimLayer);
1650
1651                    if (appTransition.isTransitionSet()) {
1652                        // If we are currently setting up for an animation, hold everything until we
1653                        // can find out what will happen.
1654                        mService.mInputMethodTargetWaitingAnim = true;
1655                        mService.mInputMethodTarget = highestTarget;
1656                        return highestPos + 1;
1657                    } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1658                            highestTarget.mWinAnimator.mAnimLayer > w.mWinAnimator.mAnimLayer) {
1659                        // If the window we are currently targeting is involved with an animation,
1660                        // and it is on top of the next target we will be over, then hold off on
1661                        // moving until that is done.
1662                        mService.mInputMethodTargetWaitingAnim = true;
1663                        mService.mInputMethodTarget = highestTarget;
1664                        return highestPos + 1;
1665                    }
1666                }
1667            }
1668        }
1669
1670        //Slog.i(TAG_WM, "Placing input method @" + (i+1));
1671        if (w != null) {
1672            if (willMove) {
1673                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1674                        + w + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1675                mService.mInputMethodTarget = w;
1676                mService.mInputMethodTargetWaitingAnim = false;
1677                if (w.mAppToken != null) {
1678                    setInputMethodAnimLayerAdjustment(
1679                            w.mAppToken.mAppAnimator.animLayerAdjustment);
1680                } else {
1681                    setInputMethodAnimLayerAdjustment(0);
1682                }
1683            }
1684
1685            // If the docked divider is visible, we still need to go through this whole excercise to
1686            // find the appropriate input method target (used for animations and dialog
1687            // adjustments), but for purposes of Z ordering we simply wish to place it above the
1688            // docked divider. Unless it is already above the divider.
1689            final WindowState dockedDivider = mDividerControllerLocked.getWindow();
1690            if (dockedDivider != null && dockedDivider.isVisibleLw()) {
1691                int dividerIndex = windows.indexOf(dockedDivider);
1692                if (dividerIndex > 0 && dividerIndex > i) {
1693                    return dividerIndex + 1;
1694                }
1695            }
1696            return i+1;
1697        }
1698        if (willMove) {
1699            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
1700                    + " to null." + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1701            mService.mInputMethodTarget = null;
1702            setInputMethodAnimLayerAdjustment(0);
1703        }
1704        return -1;
1705    }
1706
1707    private static boolean canBeImeTarget(WindowState w) {
1708        final int fl = w.mAttrs.flags & (FLAG_NOT_FOCUSABLE|FLAG_ALT_FOCUSABLE_IM);
1709        final int type = w.mAttrs.type;
1710
1711        if (fl != 0 && fl != (FLAG_NOT_FOCUSABLE | FLAG_ALT_FOCUSABLE_IM)
1712                && type != TYPE_APPLICATION_STARTING) {
1713            return false;
1714        }
1715
1716        if (DEBUG_INPUT_METHOD) {
1717            Slog.i(TAG_WM, "isVisibleOrAdding " + w + ": " + w.isVisibleOrAdding());
1718            if (!w.isVisibleOrAdding()) {
1719                Slog.i(TAG_WM, "  mSurfaceController=" + w.mWinAnimator.mSurfaceController
1720                        + " relayoutCalled=" + w.mRelayoutCalled
1721                        + " viewVis=" + w.mViewVisibility
1722                        + " policyVis=" + w.mPolicyVisibility
1723                        + " policyVisAfterAnim=" + w.mPolicyVisibilityAfterAnim
1724                        + " parentHidden=" + w.isParentWindowHidden()
1725                        + " exiting=" + w.mAnimatingExit + " destroying=" + w.mDestroying);
1726                if (w.mAppToken != null) {
1727                    Slog.i(TAG_WM, "  mAppToken.hiddenRequested=" + w.mAppToken.hiddenRequested);
1728                }
1729            }
1730        }
1731        return w.isVisibleOrAdding();
1732    }
1733
1734    private void logWindowList(final WindowList windows, String prefix) {
1735        int N = windows.size();
1736        while (N > 0) {
1737            N--;
1738            Slog.v(TAG_WM, prefix + "#" + N + ": " + windows.get(N));
1739        }
1740    }
1741
1742    boolean getNeedsMenu(WindowState win, WindowManagerPolicy.WindowState bottom) {
1743        int index = -1;
1744        WindowList windows = getWindowList();
1745        while (true) {
1746            if (win.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
1747                return win.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
1748            }
1749            // If we reached the bottom of the range of windows we are considering,
1750            // assume no menu is needed.
1751            if (win == bottom) {
1752                return false;
1753            }
1754            // The current window hasn't specified whether menu key is needed; look behind it.
1755            // First, we may need to determine the starting position.
1756            if (index < 0) {
1757                index = windows.indexOf(win);
1758            }
1759            index--;
1760            if (index < 0) {
1761                return false;
1762            }
1763            win = windows.get(index);
1764        }
1765    }
1766
1767    void setLayoutNeeded() {
1768        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
1769        mLayoutNeeded = true;
1770    }
1771
1772    void clearLayoutNeeded() {
1773        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
1774        mLayoutNeeded = false;
1775    }
1776
1777    boolean isLayoutNeeded() {
1778        return mLayoutNeeded;
1779    }
1780
1781    private int addAppWindowExisting(WindowState win, WindowList tokenWindowList) {
1782
1783        int tokenWindowsPos;
1784        // If this application has existing windows, we simply place the new window on top of
1785        // them... but keep the starting window on top.
1786        if (win.mAttrs.type == TYPE_BASE_APPLICATION) {
1787            // Base windows go behind everything else.
1788            final WindowState lowestWindow = tokenWindowList.get(0);
1789            addWindowToListBefore(win, lowestWindow);
1790            tokenWindowsPos = win.mToken.getWindowIndex(lowestWindow);
1791        } else {
1792            final AppWindowToken atoken = win.mAppToken;
1793            final int windowListPos = tokenWindowList.size();
1794            final WindowState lastWindow = tokenWindowList.get(windowListPos - 1);
1795            if (atoken != null && lastWindow == atoken.startingWindow) {
1796                addWindowToListBefore(win, lastWindow);
1797                tokenWindowsPos = win.mToken.getWindowIndex(lastWindow);
1798            } else {
1799                int newIdx = findIdxBasedOnAppTokens(win);
1800                // There is a window above this one associated with the same apptoken note that the
1801                // window could be a floating window that was created later or a window at the top
1802                // of the list of windows associated with this token.
1803                if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1804                        "not Base app: Adding window " + win + " at " + (newIdx + 1) + " of "
1805                                + mWindows.size());
1806                mWindows.add(newIdx + 1, win);
1807                if (newIdx < 0) {
1808                    // No window from token found on win's display.
1809                    tokenWindowsPos = 0;
1810                } else {
1811                    tokenWindowsPos = win.mToken.getWindowIndex(mWindows.get(newIdx)) + 1;
1812                }
1813                mService.mWindowsChanged = true;
1814            }
1815        }
1816        return tokenWindowsPos;
1817    }
1818
1819    /** Places the first input window after the second input window in the window list. */
1820    private void addWindowToListAfter(WindowState first, WindowState second) {
1821        final int i = mWindows.indexOf(second);
1822        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1823                "Adding window " + this + " at " + (i + 1) + " of " + mWindows.size()
1824                + " (after " + second + ")");
1825        mWindows.add(i + 1, first);
1826        mService.mWindowsChanged = true;
1827    }
1828
1829    /** Places the first input window before the second input window in the window list. */
1830    private void addWindowToListBefore(WindowState first, WindowState second) {
1831        int i = mWindows.indexOf(second);
1832        if (DEBUG_FOCUS || DEBUG_WINDOW_MOVEMENT || DEBUG_ADD_REMOVE) Slog.v(TAG_WM,
1833                "Adding window " + this + " at " + i + " of " + mWindows.size()
1834                + " (before " + second + ")");
1835        if (i < 0) {
1836            Slog.w(TAG_WM, "addWindowToListBefore: Unable to find " + second + " in " + mWindows);
1837            i = 0;
1838        }
1839        mWindows.add(i, first);
1840        mService.mWindowsChanged = true;
1841    }
1842
1843    /**
1844     * This method finds out the index of a window that has the same app token as win. used for z
1845     * ordering the windows in mWindows
1846     */
1847    private int findIdxBasedOnAppTokens(WindowState win) {
1848        for(int j = mWindows.size() - 1; j >= 0; j--) {
1849            final WindowState wentry = mWindows.get(j);
1850            if(wentry.mAppToken == win.mAppToken) {
1851                return j;
1852            }
1853        }
1854        return -1;
1855    }
1856
1857    private void dumpChildrenNames() {
1858        StringBuilder output = new StringBuilder();
1859        dumpChildrenNames(output, " ");
1860        Slog.v(TAG_WM, output.toString());
1861    }
1862
1863    private void dumpWindows() {
1864        Slog.v(TAG_WM, " Display #" + mDisplayId);
1865        final WindowList windows = getWindowList();
1866        for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
1867            Slog.v(TAG_WM, "  #" + winNdx + ": " + windows.get(winNdx));
1868        }
1869    }
1870
1871    void dumpTokens(PrintWriter pw, boolean dumpAll) {
1872        if (mTokenMap.isEmpty()) {
1873            return;
1874        }
1875        pw.println("  Display #" + mDisplayId);
1876        final Iterator<WindowToken> it = mTokenMap.values().iterator();
1877        while (it.hasNext()) {
1878            final WindowToken token = it.next();
1879            pw.print("  ");
1880            pw.print(token);
1881            if (dumpAll) {
1882                pw.println(':');
1883                token.dump(pw, "    ");
1884            } else {
1885                pw.println();
1886            }
1887        }
1888    }
1889
1890    void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
1891        final int count = mWindows.size();
1892        for (int j = 0; j < count; j++) {
1893            final WindowStateAnimator wAnim = mWindows.get(j).mWinAnimator;
1894            pw.println(subPrefix + "Window #" + j + ": " + wAnim);
1895        }
1896    }
1897
1898    void enableSurfaceTrace(FileDescriptor fd) {
1899        for (int i = mWindows.size() - 1; i >= 0; i--) {
1900            final WindowState win = mWindows.get(i);
1901            win.mWinAnimator.enableSurfaceTrace(fd);
1902        }
1903    }
1904
1905    void disableSurfaceTrace() {
1906        for (int i = mWindows.size() - 1; i >= 0; i--) {
1907            final WindowState win = mWindows.get(i);
1908            win.mWinAnimator.disableSurfaceTrace();
1909        }
1910    }
1911
1912    boolean checkWaitingForWindows() {
1913
1914        boolean haveBootMsg = false;
1915        boolean haveApp = false;
1916        // if the wallpaper service is disabled on the device, we're never going to have
1917        // wallpaper, don't bother waiting for it
1918        boolean haveWallpaper = false;
1919        boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
1920                com.android.internal.R.bool.config_enableWallpaperService)
1921                && !mService.mOnlyCore;
1922        boolean haveKeyguard = true;
1923        final int count = mWindows.size();
1924        for (int i = 0; i < count; i++) {
1925            final WindowState w = mWindows.get(i);
1926            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
1927                return true;
1928            }
1929            if (w.isDrawnLw()) {
1930                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
1931                    haveBootMsg = true;
1932                } else if (w.mAttrs.type == TYPE_APPLICATION
1933                        || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
1934                    haveApp = true;
1935                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
1936                    haveWallpaper = true;
1937                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
1938                    haveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
1939                }
1940            }
1941        }
1942
1943        if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
1944                "******** booted=" + mService.mSystemBooted
1945                + " msg=" + mService.mShowingBootMessages
1946                + " haveBoot=" + haveBootMsg + " haveApp=" + haveApp
1947                + " haveWall=" + haveWallpaper + " wallEnabled=" + wallpaperEnabled
1948                + " haveKeyguard=" + haveKeyguard);
1949
1950        // If we are turning on the screen to show the boot message, don't do it until the boot
1951        // message is actually displayed.
1952        if (!mService.mSystemBooted && !haveBootMsg) {
1953            return true;
1954        }
1955
1956        // If we are turning on the screen after the boot is completed normally, don't do so until
1957        // we have the application and wallpaper.
1958        if (mService.mSystemBooted && ((!haveApp && !haveKeyguard) ||
1959                (wallpaperEnabled && !haveWallpaper))) {
1960            return true;
1961        }
1962
1963        return false;
1964    }
1965
1966    void updateWindowsForAnimator(WindowAnimator animator) {
1967        final WindowManagerPolicy policy = animator.mPolicy;
1968        final int keyguardGoingAwayFlags = animator.mKeyguardGoingAwayFlags;
1969        final boolean keyguardGoingAwayToShade =
1970                (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_TO_SHADE) != 0;
1971        final boolean keyguardGoingAwayNoAnimation =
1972                (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_NO_WINDOW_ANIMATIONS) != 0;
1973        final boolean keyguardGoingAwayWithWallpaper =
1974                (keyguardGoingAwayFlags & KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER) != 0;
1975
1976        if (animator.mKeyguardGoingAway) {
1977            for (int i = mWindows.size() - 1; i >= 0; i--) {
1978                WindowState win = mWindows.get(i);
1979                if (!policy.isKeyguardHostWindow(win.mAttrs)) {
1980                    continue;
1981                }
1982                final WindowStateAnimator winAnimator = win.mWinAnimator;
1983                if (policy.isKeyguardShowingAndNotOccluded()) {
1984                    if (!winAnimator.mAnimating) {
1985                        if (DEBUG_KEYGUARD) Slog.d(TAG,
1986                                "updateWindowsForAnimator: creating delay animation");
1987
1988                        // Create a new animation to delay until keyguard is gone on its own.
1989                        winAnimator.mAnimation = new AlphaAnimation(1.0f, 1.0f);
1990                        winAnimator.mAnimation.setDuration(KEYGUARD_ANIM_TIMEOUT_MS);
1991                        winAnimator.mAnimationIsEntrance = false;
1992                        winAnimator.mAnimationStartTime = -1;
1993                        winAnimator.mKeyguardGoingAwayAnimation = true;
1994                        winAnimator.mKeyguardGoingAwayWithWallpaper
1995                                = keyguardGoingAwayWithWallpaper;
1996                    }
1997                } else {
1998                    if (DEBUG_KEYGUARD) Slog.d(TAG,
1999                            "updateWindowsForAnimator: StatusBar is no longer keyguard");
2000                    animator.mKeyguardGoingAway = false;
2001                    winAnimator.clearAnimation();
2002                }
2003                break;
2004            }
2005        }
2006
2007        animator.mForceHiding = KEYGUARD_NOT_SHOWN;
2008
2009        boolean wallpaperInUnForceHiding = false;
2010        boolean startingInUnForceHiding = false;
2011        ArrayList<WindowStateAnimator> unForceHiding = null;
2012        WindowState wallpaper = null;
2013        final WallpaperController wallpaperController = mWallpaperController;
2014        for (int i = mWindows.size() - 1; i >= 0; i--) {
2015            WindowState win = mWindows.get(i);
2016            WindowStateAnimator winAnimator = win.mWinAnimator;
2017            final int flags = win.mAttrs.flags;
2018            boolean canBeForceHidden = policy.canBeForceHidden(win, win.mAttrs);
2019            boolean shouldBeForceHidden = animator.shouldForceHide(win);
2020            if (winAnimator.hasSurface()) {
2021                final boolean wasAnimating = winAnimator.mWasAnimating;
2022                final boolean nowAnimating = winAnimator.stepAnimationLocked(animator.mCurrentTime);
2023                winAnimator.mWasAnimating = nowAnimating;
2024                animator.orAnimating(nowAnimating);
2025
2026                if (DEBUG_WALLPAPER) Slog.v(TAG,
2027                        win + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
2028
2029                if (wasAnimating && !winAnimator.mAnimating
2030                        && wallpaperController.isWallpaperTarget(win)) {
2031                    animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2032                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2033                    if (DEBUG_LAYOUT_REPEATS) {
2034                        mService.mWindowPlacerLocked.debugLayoutRepeats(
2035                                "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
2036                    }
2037                }
2038
2039                if (policy.isForceHiding(win.mAttrs)) {
2040                    if (!wasAnimating && nowAnimating) {
2041                        if (DEBUG_KEYGUARD || DEBUG_ANIM || DEBUG_VISIBILITY) Slog.v(TAG,
2042                                "Animation started that could impact force hide: " + win);
2043                        animator.mBulkUpdateParams |= SET_FORCE_HIDING_CHANGED;
2044                        pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2045                        if (DEBUG_LAYOUT_REPEATS) {
2046                            mService.mWindowPlacerLocked.debugLayoutRepeats(
2047                                    "updateWindowsAndWallpaperLocked 3", pendingLayoutChanges);
2048                        }
2049                        mService.mFocusMayChange = true;
2050                    } else if (animator.mKeyguardGoingAway && !nowAnimating) {
2051                        // Timeout!!
2052                        Slog.e(TAG, "Timeout waiting for animation to startup");
2053                        policy.startKeyguardExitAnimation(0, 0);
2054                        animator.mKeyguardGoingAway = false;
2055                    }
2056                    if (win.isReadyForDisplay()) {
2057                        if (nowAnimating && win.mWinAnimator.mKeyguardGoingAwayAnimation) {
2058                            animator.mForceHiding = KEYGUARD_ANIMATING_OUT;
2059                        } else {
2060                            animator.mForceHiding = win.isDrawnLw()
2061                                    ? KEYGUARD_SHOWN : KEYGUARD_NOT_SHOWN;
2062                        }
2063                    }
2064                    if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
2065                            "Force hide " + animator.forceHidingToString()
2066                                    + " hasSurface=" + win.mHasSurface
2067                                    + " policyVis=" + win.mPolicyVisibility
2068                                    + " destroying=" + win.mDestroying
2069                                    + " parentHidden=" + win.isParentWindowHidden()
2070                                    + " vis=" + win.mViewVisibility
2071                                    + " hidden=" + win.mToken.hidden
2072                                    + " anim=" + win.mWinAnimator.mAnimation);
2073                } else if (canBeForceHidden) {
2074                    if (shouldBeForceHidden) {
2075                        if (!win.hideLw(false, false)) {
2076                            // Was already hidden
2077                            continue;
2078                        }
2079                        if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
2080                                "Now policy hidden: " + win);
2081                    } else {
2082                        final Animation postKeyguardExitAnimation =
2083                                animator.mPostKeyguardExitAnimation;
2084                        boolean applyExistingExitAnimation = postKeyguardExitAnimation != null
2085                                && !postKeyguardExitAnimation.hasEnded()
2086                                && !winAnimator.mKeyguardGoingAwayAnimation
2087                                && win.hasDrawnLw()
2088                                && !win.isChildWindow()
2089                                && !win.mIsImWindow
2090                                && isDefaultDisplay;
2091
2092                        // If the window is already showing and we don't need to apply an existing
2093                        // Keyguard exit animation, skip.
2094                        if (!win.showLw(false, false) && !applyExistingExitAnimation) {
2095                            continue;
2096                        }
2097                        final boolean visibleNow = win.isVisibleNow();
2098                        if (!visibleNow) {
2099                            // Couldn't really show, must showLw() again when win becomes visible.
2100                            win.hideLw(false, false);
2101                            continue;
2102                        }
2103                        if (DEBUG_KEYGUARD || DEBUG_VISIBILITY) Slog.v(TAG,
2104                                "Now policy shown: " + win);
2105                        if ((animator.mBulkUpdateParams & SET_FORCE_HIDING_CHANGED) != 0
2106                                && !win.isChildWindow()) {
2107                            if (unForceHiding == null) {
2108                                unForceHiding = new ArrayList<>();
2109                            }
2110                            unForceHiding.add(winAnimator);
2111                            if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
2112                                wallpaperInUnForceHiding = true;
2113                            }
2114                            if (win.mAttrs.type == TYPE_APPLICATION_STARTING) {
2115                                startingInUnForceHiding = true;
2116                            }
2117                        } else if (applyExistingExitAnimation) {
2118                            // We're already in the middle of an animation. Use the existing
2119                            // animation to bring in this window.
2120                            if (DEBUG_KEYGUARD) Slog.v(TAG,
2121                                    "Applying existing Keyguard exit animation to new window: win="
2122                                            + win);
2123
2124                            final Animation a = policy.createForceHideEnterAnimation(false,
2125                                    keyguardGoingAwayToShade);
2126                            winAnimator.setAnimation(a, postKeyguardExitAnimation.getStartTime(),
2127                                    STACK_CLIP_BEFORE_ANIM);
2128                            winAnimator.mKeyguardGoingAwayAnimation = true;
2129                            winAnimator.mKeyguardGoingAwayWithWallpaper
2130                                    = keyguardGoingAwayWithWallpaper;
2131                        }
2132                        final WindowState currentFocus = mService.mCurrentFocus;
2133                        if (currentFocus == null || currentFocus.mLayer < win.mLayer) {
2134                            // We are showing on top of the current
2135                            // focus, so re-evaluate focus to make
2136                            // sure it is correct.
2137                            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG,
2138                                    "updateWindowsForAnimator: setting mFocusMayChange true");
2139                            mService.mFocusMayChange = true;
2140                        }
2141                    }
2142                    if ((flags & FLAG_SHOW_WALLPAPER) != 0) {
2143                        animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2144                        pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2145                        if (DEBUG_LAYOUT_REPEATS) {
2146                            mService.mWindowPlacerLocked.debugLayoutRepeats(
2147                                    "updateWindowsAndWallpaperLocked 4", pendingLayoutChanges);
2148                        }
2149                    }
2150                }
2151            }
2152
2153            // If the window doesn't have a surface, the only thing we care about is the correct
2154            // policy visibility.
2155            else if (canBeForceHidden) {
2156                if (shouldBeForceHidden) {
2157                    win.hideLw(false, false);
2158                } else {
2159                    win.showLw(false, false);
2160                }
2161            }
2162
2163            final AppWindowToken atoken = win.mAppToken;
2164            if (winAnimator.mDrawState == READY_TO_SHOW) {
2165                if (atoken == null || atoken.allDrawn) {
2166                    if (win.performShowLocked()) {
2167                        pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
2168                        if (DEBUG_LAYOUT_REPEATS) {
2169                            mService.mWindowPlacerLocked.debugLayoutRepeats(
2170                                    "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
2171                        }
2172                    }
2173                }
2174            }
2175            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
2176            if (appAnimator != null && appAnimator.thumbnail != null) {
2177                if (appAnimator.thumbnailTransactionSeq != animator.mAnimTransactionSequence) {
2178                    appAnimator.thumbnailTransactionSeq = animator.mAnimTransactionSequence;
2179                    appAnimator.thumbnailLayer = 0;
2180                }
2181                if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
2182                    appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
2183                }
2184            }
2185            if (win.mIsWallpaper) {
2186                wallpaper = win;
2187            }
2188        } // end forall windows
2189
2190        // If we have windows that are being shown due to them no longer being force-hidden, apply
2191        // the appropriate animation to them if animations are not disabled.
2192        if (unForceHiding != null) {
2193            if (!keyguardGoingAwayNoAnimation) {
2194                boolean first = true;
2195                for (int i=unForceHiding.size()-1; i>=0; i--) {
2196                    final WindowStateAnimator winAnimator = unForceHiding.get(i);
2197                    final Animation a = policy.createForceHideEnterAnimation(
2198                            wallpaperInUnForceHiding && !startingInUnForceHiding,
2199                            keyguardGoingAwayToShade);
2200                    if (a != null) {
2201                        if (DEBUG_KEYGUARD) Slog.v(TAG,
2202                                "Starting keyguard exit animation on window " + winAnimator.mWin);
2203                        winAnimator.setAnimation(a, STACK_CLIP_BEFORE_ANIM);
2204                        winAnimator.mKeyguardGoingAwayAnimation = true;
2205                        winAnimator.mKeyguardGoingAwayWithWallpaper
2206                                = keyguardGoingAwayWithWallpaper;
2207                        if (first) {
2208                            animator.mPostKeyguardExitAnimation = a;
2209                            animator.mPostKeyguardExitAnimation.setStartTime(animator.mCurrentTime);
2210                            first = false;
2211                        }
2212                    }
2213                }
2214            } else if (animator.mKeyguardGoingAway) {
2215                policy.startKeyguardExitAnimation(animator.mCurrentTime, 0 /* duration */);
2216                animator.mKeyguardGoingAway = false;
2217            }
2218
2219
2220            // Wallpaper is going away in un-force-hide motion, animate it as well.
2221            if (!wallpaperInUnForceHiding && wallpaper != null && !keyguardGoingAwayNoAnimation) {
2222                if (DEBUG_KEYGUARD) Slog.d(TAG,
2223                        "updateWindowsForAnimator: wallpaper animating away");
2224                final Animation a = policy.createForceHideWallpaperExitAnimation(
2225                        keyguardGoingAwayToShade);
2226                if (a != null) {
2227                    wallpaper.mWinAnimator.setAnimation(a);
2228                }
2229            }
2230        }
2231
2232        if (animator.mPostKeyguardExitAnimation != null) {
2233            // We're in the midst of a keyguard exit animation.
2234            if (animator.mKeyguardGoingAway) {
2235                policy.startKeyguardExitAnimation(animator.mCurrentTime +
2236                                animator.mPostKeyguardExitAnimation.getStartOffset(),
2237                        animator.mPostKeyguardExitAnimation.getDuration());
2238                animator.mKeyguardGoingAway = false;
2239            }
2240            // mPostKeyguardExitAnimation might either be ended normally, cancelled, or "orphaned",
2241            // meaning that the window it was running on was removed. We check for hasEnded() for
2242            // ended normally and cancelled case, and check the time for the "orphaned" case.
2243            else if (animator.mPostKeyguardExitAnimation.hasEnded()
2244                    || animator.mCurrentTime - animator.mPostKeyguardExitAnimation.getStartTime()
2245                    > animator.mPostKeyguardExitAnimation.getDuration()) {
2246                // Done with the animation, reset.
2247                if (DEBUG_KEYGUARD) Slog.v(TAG, "Done with Keyguard exit animations.");
2248                animator.mPostKeyguardExitAnimation = null;
2249            }
2250        }
2251
2252        final WindowState winShowWhenLocked = (WindowState) policy.getWinShowWhenLockedLw();
2253        if (winShowWhenLocked != null) {
2254            animator.mLastShowWinWhenLocked = winShowWhenLocked;
2255        }
2256    }
2257
2258    void updateWallpaperForAnimator(WindowAnimator animator) {
2259        resetAnimationBackgroundAnimator();
2260
2261        final WindowList windows = mWindows;
2262        WindowState detachedWallpaper = null;
2263
2264        for (int i = windows.size() - 1; i >= 0; i--) {
2265            final WindowState win = windows.get(i);
2266            final WindowStateAnimator winAnimator = win.mWinAnimator;
2267            if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
2268                continue;
2269            }
2270
2271            final int flags = win.mAttrs.flags;
2272
2273            // If this window is animating, make a note that we have an animating window and take
2274            // care of a request to run a detached wallpaper animation.
2275            if (winAnimator.mAnimating) {
2276                if (winAnimator.mAnimation != null) {
2277                    if ((flags & FLAG_SHOW_WALLPAPER) != 0
2278                            && winAnimator.mAnimation.getDetachWallpaper()) {
2279                        detachedWallpaper = win;
2280                    }
2281                    final int color = winAnimator.mAnimation.getBackgroundColor();
2282                    if (color != 0) {
2283                        final TaskStack stack = win.getStack();
2284                        if (stack != null) {
2285                            stack.setAnimationBackground(winAnimator, color);
2286                        }
2287                    }
2288                }
2289                animator.setAnimating(true);
2290            }
2291
2292            // If this window's app token is running a detached wallpaper animation, make a note so
2293            // we can ensure the wallpaper is displayed behind it.
2294            final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
2295            if (appAnimator != null && appAnimator.animation != null
2296                    && appAnimator.animating) {
2297                if ((flags & FLAG_SHOW_WALLPAPER) != 0
2298                        && appAnimator.animation.getDetachWallpaper()) {
2299                    detachedWallpaper = win;
2300                }
2301
2302                final int color = appAnimator.animation.getBackgroundColor();
2303                if (color != 0) {
2304                    final TaskStack stack = win.getStack();
2305                    if (stack != null) {
2306                        stack.setAnimationBackground(winAnimator, color);
2307                    }
2308                }
2309            }
2310        } // end forall windows
2311
2312        if (animator.mWindowDetachedWallpaper != detachedWallpaper) {
2313            if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
2314                    + animator.mWindowDetachedWallpaper + " to " + detachedWallpaper);
2315            animator.mWindowDetachedWallpaper = detachedWallpaper;
2316            animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
2317        }
2318    }
2319
2320    void prepareWindowSurfaces() {
2321        final int count = mWindows.size();
2322        for (int j = 0; j < count; j++) {
2323            mWindows.get(j).mWinAnimator.prepareSurfaceLocked(true);
2324        }
2325    }
2326
2327    boolean inputMethodClientHasFocus(IInputMethodClient client) {
2328        // The focus for the client is the window immediately below where we would place the input
2329        // method window.
2330        int idx = findDesiredInputMethodWindowIndex(false);
2331        if (idx <= 0) {
2332            return false;
2333        }
2334
2335        WindowState imFocus = mWindows.get(idx - 1);
2336        if (DEBUG_INPUT_METHOD) {
2337            Slog.i(TAG_WM, "Desired input method target: " + imFocus);
2338            Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
2339            Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
2340        }
2341
2342        if (imFocus == null) {
2343            return false;
2344        }
2345
2346        // This may be a starting window, in which case we still want to count it as okay.
2347        if (imFocus.mAttrs.type == TYPE_APPLICATION_STARTING && imFocus.mAppToken != null) {
2348            // The client has definitely started, so it really should have a window in this app
2349            // token. Let's look for it.
2350            final WindowState w = imFocus.mAppToken.getFirstNonStartingWindow();
2351            if (w != null) {
2352                if (DEBUG_INPUT_METHOD) Slog.i(TAG_WM, "Switching to real app window: " + w);
2353                imFocus = w;
2354            }
2355        }
2356
2357        final IInputMethodClient imeClient = imFocus.mSession.mClient;
2358
2359        if (DEBUG_INPUT_METHOD) {
2360            Slog.i(TAG_WM, "IM target client: " + imeClient);
2361            if (imeClient != null) {
2362                Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
2363                Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
2364            }
2365        }
2366
2367        return imeClient != null && imeClient.asBinder() == client.asBinder();
2368    }
2369
2370    boolean hasSecureWindowOnScreen() {
2371        for (int i = mWindows.size() - 1; i >= 0; --i) {
2372            final WindowState ws = mWindows.get(i);
2373            if (ws.isOnScreen() && (ws.mAttrs.flags & FLAG_SECURE) != 0) {
2374                return true;
2375            }
2376        }
2377        return false;
2378    }
2379
2380    void updateSystemUiVisibility(int visibility, int globalDiff) {
2381        for (int i = mWindows.size() - 1; i >= 0; --i) {
2382            final WindowState ws = mWindows.get(i);
2383            try {
2384                int curValue = ws.mSystemUiVisibility;
2385                int diff = (curValue ^ visibility) & globalDiff;
2386                int newValue = (curValue & ~diff) | (visibility & diff);
2387                if (newValue != curValue) {
2388                    ws.mSeq++;
2389                    ws.mSystemUiVisibility = newValue;
2390                }
2391                if (newValue != curValue || ws.mAttrs.hasSystemUiListeners) {
2392                    ws.mClient.dispatchSystemUiVisibilityChanged(ws.mSeq,
2393                            visibility, newValue, diff);
2394                }
2395            } catch (RemoteException e) {
2396                // so sorry
2397            }
2398        }
2399    }
2400
2401    void onWindowFreezeTimeout() {
2402        Slog.w(TAG_WM, "Window freeze timeout expired.");
2403        mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
2404        for (int i = mWindows.size() - 1; i >= 0; --i) {
2405            final WindowState w = mWindows.get(i);
2406            if (!w.mOrientationChanging) {
2407                continue;
2408            }
2409            w.mOrientationChanging = false;
2410            w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
2411                    - mService.mDisplayFreezeTime);
2412            Slog.w(TAG_WM, "Force clearing orientation change: " + w);
2413        }
2414        mService.mWindowPlacerLocked.performSurfacePlacement();
2415    }
2416
2417    void waitForAllWindowsDrawn() {
2418        final WindowManagerPolicy policy = mService.mPolicy;
2419        for (int winNdx = mWindows.size() - 1; winNdx >= 0; --winNdx) {
2420            final WindowState win = mWindows.get(winNdx);
2421            final boolean isForceHiding = policy.isForceHiding(win.mAttrs);
2422            final boolean keyguard = policy.isKeyguardHostWindow(win.mAttrs);
2423            if (win.isVisibleLw() && (win.mAppToken != null || isForceHiding || keyguard)) {
2424                win.mWinAnimator.mDrawState = DRAW_PENDING;
2425                // Force add to mResizingWindows.
2426                win.mLastContentInsets.set(-1, -1, -1, -1);
2427                mService.mWaitingForDrawn.add(win);
2428
2429                // No need to wait for the windows below Keyguard.
2430                if (isForceHiding) {
2431                    return;
2432                }
2433            }
2434        }
2435    }
2436
2437    static final class GetWindowOnDisplaySearchResult {
2438        boolean reachedToken;
2439        WindowState foundWindow;
2440
2441        void reset() {
2442            reachedToken = false;
2443            foundWindow = null;
2444        }
2445    }
2446
2447    static final class TaskForResizePointSearchResult {
2448        boolean searchDone;
2449        Task taskForResize;
2450
2451        void reset() {
2452            searchDone = false;
2453            taskForResize = null;
2454        }
2455    }
2456
2457    /**
2458     * Base class for any direct child window container of {@link #DisplayContent} need to inherit
2459     * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
2460     * homogeneous children type which is currently required by sub-classes of
2461     * {@link WindowContainer} class.
2462     */
2463    static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
2464
2465        int size() {
2466            return mChildren.size();
2467        }
2468
2469        E get(int index) {
2470            return mChildren.get(index);
2471        }
2472
2473        @Override
2474        boolean fillsParent() {
2475            return true;
2476        }
2477
2478        @Override
2479        boolean isVisible() {
2480            return true;
2481        }
2482    }
2483
2484    /**
2485     * Window container class that contains all containers on this display relating to Apps.
2486     * I.e Activities.
2487     */
2488    private class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
2489
2490        void attachStack(TaskStack stack, boolean onTop) {
2491            if (stack.mStackId == HOME_STACK_ID) {
2492                if (mHomeStack != null) {
2493                    throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
2494                }
2495                mHomeStack = stack;
2496            }
2497            addChild(stack, onTop);
2498            stack.onDisplayChanged(DisplayContent.this);
2499        }
2500
2501        void moveStack(TaskStack stack, boolean toTop) {
2502            if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
2503                // This stack is always-on-top silly...
2504                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
2505                return;
2506            }
2507
2508            if (!mChildren.contains(stack)) {
2509                Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
2510            }
2511            removeChild(stack);
2512            addChild(stack, toTop);
2513        }
2514
2515        private void addChild(TaskStack stack, boolean toTop) {
2516            int addIndex = toTop ? mChildren.size() : 0;
2517
2518            if (toTop
2519                    && mService.isStackVisibleLocked(PINNED_STACK_ID)
2520                    && stack.mStackId != PINNED_STACK_ID) {
2521                // The pinned stack is always the top most stack (always-on-top) when it is visible.
2522                // So, stack is moved just below the pinned stack.
2523                addIndex--;
2524                TaskStack topStack = mChildren.get(addIndex);
2525                if (topStack.mStackId != PINNED_STACK_ID) {
2526                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
2527                }
2528            }
2529            addChild(stack, addIndex);
2530            setLayoutNeeded();
2531        }
2532
2533        @Override
2534        int getOrientation() {
2535            if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
2536                    || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
2537                // Apps and their containers are not allowed to specify an orientation while the
2538                // docked or freeform stack is visible...except for the home stack/task if the
2539                // docked stack is minimized and it actually set something.
2540                if (mHomeStack != null && mHomeStack.isVisible()
2541                        && mDividerControllerLocked.isMinimizedDock()) {
2542                    final int orientation = mHomeStack.getOrientation();
2543                    if (orientation != SCREEN_ORIENTATION_UNSET) {
2544                        return orientation;
2545                    }
2546                }
2547                return SCREEN_ORIENTATION_UNSPECIFIED;
2548            }
2549
2550            final int orientation = super.getOrientation();
2551            if (orientation != SCREEN_ORIENTATION_UNSET
2552                    && orientation != SCREEN_ORIENTATION_BEHIND) {
2553                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
2554                        "App is requesting an orientation, return " + orientation);
2555                return orientation;
2556            }
2557
2558            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
2559                    "No app is requesting an orientation, return " + mService.mLastOrientation);
2560            // The next app has not been requested to be visible, so we keep the current orientation
2561            // to prevent freezing/unfreezing the display too early.
2562            return mService.mLastOrientation;
2563        }
2564    }
2565
2566    /**
2567     * Window container class that contains all containers on this display that are not related to
2568     * Apps. E.g. status bar.
2569     */
2570    private static class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
2571
2572    }
2573}
2574