DisplayContent.java revision 5d7e7f136e349e6cde86943dd03e7edd9ec92e6e
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
19import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
20import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
21import static android.app.ActivityManager.StackId.HOME_STACK_ID;
22import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
23import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
24import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
25import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
26import static android.view.Display.DEFAULT_DISPLAY;
27import static android.view.Display.FLAG_PRIVATE;
28import static android.view.Surface.ROTATION_0;
29import static android.view.Surface.ROTATION_180;
30import static android.view.Surface.ROTATION_270;
31import static android.view.Surface.ROTATION_90;
32import static android.view.View.GONE;
33import static android.view.WindowManager.DOCKED_BOTTOM;
34import static android.view.WindowManager.DOCKED_INVALID;
35import static android.view.WindowManager.DOCKED_TOP;
36import static android.view.WindowManager.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.PRIVATE_FLAG_KEYGUARD;
44import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
45import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
46import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
47import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
48import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
49import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
50import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
51import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
52import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
53import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
54import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
55import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
56import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
57import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
58import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
59import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
60import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_BOOT;
61import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
62import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS;
63import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
64import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_INPUT_METHOD;
65import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
66import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
67import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
68import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
69import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
70import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREEN_ON;
71import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
72import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
73import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
74import static com.android.server.wm.WindowManagerDebugConfig.SHOW_STACK_CRAWLS;
75import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
76import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
77import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
78import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
79import static com.android.server.wm.WindowManagerService.H.UPDATE_DOCKED_STACK_DIVIDER;
80import static com.android.server.wm.WindowManagerService.H.WINDOW_HIDE_TIMEOUT;
81import static com.android.server.wm.WindowManagerService.LAYOUT_REPEAT_THRESHOLD;
82import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
83import static com.android.server.wm.WindowManagerService.TYPE_LAYER_OFFSET;
84import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
85import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_TIMEOUT;
86import static com.android.server.wm.WindowManagerService.dipToPixel;
87import static com.android.server.wm.WindowManagerService.logSurface;
88import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
89import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
90import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
91import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
92
93import android.annotation.NonNull;
94import android.app.ActivityManager.StackId;
95import android.content.res.Configuration;
96import android.graphics.Bitmap;
97import android.graphics.Matrix;
98import android.graphics.Rect;
99import android.graphics.RectF;
100import android.graphics.Region;
101import android.graphics.Region.Op;
102import android.hardware.display.DisplayManagerInternal;
103import android.os.Debug;
104import android.os.Handler;
105import android.os.IBinder;
106import android.os.RemoteException;
107import android.os.SystemClock;
108import android.util.DisplayMetrics;
109import android.util.Slog;
110import android.view.Display;
111import android.view.DisplayInfo;
112import android.view.Surface;
113import android.view.SurfaceControl;
114import android.view.WindowManagerPolicy;
115
116import com.android.internal.util.ToBooleanFunction;
117import com.android.internal.view.IInputMethodClient;
118
119import java.io.FileDescriptor;
120import java.io.PrintWriter;
121import java.util.ArrayList;
122import java.util.Comparator;
123import java.util.HashMap;
124import java.util.Iterator;
125import java.util.LinkedList;
126import java.util.List;
127import java.util.function.Consumer;
128import java.util.function.Predicate;
129
130/**
131 * Utility class for keeping track of the WindowStates and other pertinent contents of a
132 * particular Display.
133 *
134 * IMPORTANT: No method from this class should ever be used without holding
135 * WindowManagerService.mWindowMap.
136 */
137class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
138    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
139
140    /** Unique identifier of this stack. */
141    private final int mDisplayId;
142
143    /** The containers below are the only child containers the display can have. */
144    // Contains all window containers that are related to apps (Activities)
145    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
146    // Contains all non-app window containers that should be displayed above the app containers
147    // (e.g. Status bar)
148    private final NonAppWindowContainers mAboveAppWindowsContainers =
149            new NonAppWindowContainers("mAboveAppWindowsContainers");
150    // Contains all non-app window containers that should be displayed below the app containers
151    // (e.g. Wallpaper).
152    private final NonAppWindowContainers mBelowAppWindowsContainers =
153            new NonAppWindowContainers("mBelowAppWindowsContainers");
154    // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
155    // on the IME target. We mainly have this container grouping so we can keep track of all the IME
156    // window containers together and move them in-sync if/when needed.
157    private final NonAppWindowContainers mImeWindowsContainers =
158            new NonAppWindowContainers("mImeWindowsContainers");
159
160    private WindowState mTmpWindow;
161    private WindowState mTmpWindow2;
162    private WindowAnimator mTmpWindowAnimator;
163    private boolean mTmpRecoveringMemory;
164    private boolean mUpdateImeTarget;
165    private boolean mTmpInitial;
166
167    // Mapping from a token IBinder to a WindowToken object on this display.
168    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
169
170    int mInitialDisplayWidth = 0;
171    int mInitialDisplayHeight = 0;
172    int mInitialDisplayDensity = 0;
173    int mBaseDisplayWidth = 0;
174    int mBaseDisplayHeight = 0;
175    int mBaseDisplayDensity = 0;
176    boolean mDisplayScalingDisabled;
177    private final DisplayInfo mDisplayInfo = new DisplayInfo();
178    private final Display mDisplay;
179    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
180
181    Rect mBaseDisplayRect = new Rect();
182    private Rect mContentRect = new Rect();
183
184    // Accessed directly by all users.
185    private boolean mLayoutNeeded;
186    int pendingLayoutChanges;
187    // TODO(multi-display): remove some of the usages.
188    boolean isDefaultDisplay;
189
190    /** Window tokens that are in the process of exiting, but still on screen for animations. */
191    final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
192
193    /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
194     * (except a future lockscreen TaskStack) moves to the top. */
195    private TaskStack mHomeStack = null;
196
197    /** Detect user tapping outside of current focused task bounds .*/
198    TaskTapPointerEventListener mTapDetector;
199
200    /** Detect user tapping outside of current focused stack bounds .*/
201    private Region mTouchExcludeRegion = new Region();
202
203    /** Save allocating when calculating rects */
204    private final Rect mTmpRect = new Rect();
205    private final Rect mTmpRect2 = new Rect();
206    private final RectF mTmpRectF = new RectF();
207    private final Matrix mTmpMatrix = new Matrix();
208    private final Region mTmpRegion = new Region();
209
210    WindowManagerService mService;
211
212    /** Remove this display when animation on it has completed. */
213    private boolean mDeferredRemoval;
214
215    final DockedStackDividerController mDividerControllerLocked;
216    final PinnedStackController mPinnedStackControllerLocked;
217
218    DimLayerController mDimLayerController;
219
220    final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
221
222    private boolean mHaveBootMsg = false;
223    private boolean mHaveApp = false;
224    private boolean mHaveWallpaper = false;
225    private boolean mHaveKeyguard = true;
226
227    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
228
229    private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
230            new TaskForResizePointSearchResult();
231    private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
232            new ApplySurfaceChangesTransactionState();
233    private final ScreenshotApplicationState mScreenshotApplicationState =
234            new ScreenshotApplicationState();
235
236    // True if this display is in the process of being removed. Used to determine if the removal of
237    // the display's direct children should be allowed.
238    private boolean mRemovingDisplay = false;
239
240    private final WindowLayersController mLayersController;
241    WallpaperController mWallpaperController;
242    int mInputMethodAnimLayerAdjustment;
243
244    private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
245        WindowStateAnimator winAnimator = w.mWinAnimator;
246        if (winAnimator.hasSurface()) {
247            final boolean wasAnimating = winAnimator.mWasAnimating;
248            final boolean nowAnimating = winAnimator.stepAnimationLocked(
249                    mTmpWindowAnimator.mCurrentTime);
250            winAnimator.mWasAnimating = nowAnimating;
251            mTmpWindowAnimator.orAnimating(nowAnimating);
252
253            if (DEBUG_WALLPAPER) Slog.v(TAG,
254                    w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
255
256            if (wasAnimating && !winAnimator.mAnimating
257                    && mWallpaperController.isWallpaperTarget(w)) {
258                mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
259                pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
260                if (DEBUG_LAYOUT_REPEATS) {
261                    mService.mWindowPlacerLocked.debugLayoutRepeats(
262                            "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
263                }
264            }
265        }
266
267        final AppWindowToken atoken = w.mAppToken;
268        if (winAnimator.mDrawState == READY_TO_SHOW) {
269            if (atoken == null || atoken.allDrawn) {
270                if (w.performShowLocked()) {
271                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
272                    if (DEBUG_LAYOUT_REPEATS) {
273                        mService.mWindowPlacerLocked.debugLayoutRepeats(
274                                "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
275                    }
276                }
277            }
278        }
279        final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
280        if (appAnimator != null && appAnimator.thumbnail != null) {
281            if (appAnimator.thumbnailTransactionSeq
282                    != mTmpWindowAnimator.mAnimTransactionSequence) {
283                appAnimator.thumbnailTransactionSeq =
284                        mTmpWindowAnimator.mAnimTransactionSequence;
285                appAnimator.thumbnailLayer = 0;
286            }
287            if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
288                appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
289            }
290        }
291    };
292
293    private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
294        final WindowStateAnimator winAnimator = w.mWinAnimator;
295        if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
296            return;
297        }
298
299        final int flags = w.mAttrs.flags;
300
301        // If this window is animating, make a note that we have an animating window and take
302        // care of a request to run a detached wallpaper animation.
303        if (winAnimator.mAnimating) {
304            if (winAnimator.mAnimation != null) {
305                if ((flags & FLAG_SHOW_WALLPAPER) != 0
306                        && winAnimator.mAnimation.getDetachWallpaper()) {
307                    mTmpWindow = w;
308                }
309                final int color = winAnimator.mAnimation.getBackgroundColor();
310                if (color != 0) {
311                    final TaskStack stack = w.getStack();
312                    if (stack != null) {
313                        stack.setAnimationBackground(winAnimator, color);
314                    }
315                }
316            }
317            mTmpWindowAnimator.setAnimating(true);
318        }
319
320        // If this window's app token is running a detached wallpaper animation, make a note so
321        // we can ensure the wallpaper is displayed behind it.
322        final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
323        if (appAnimator != null && appAnimator.animation != null
324                && appAnimator.animating) {
325            if ((flags & FLAG_SHOW_WALLPAPER) != 0
326                    && appAnimator.animation.getDetachWallpaper()) {
327                mTmpWindow = w;
328            }
329
330            final int color = appAnimator.animation.getBackgroundColor();
331            if (color != 0) {
332                final TaskStack stack = w.getStack();
333                if (stack != null) {
334                    stack.setAnimationBackground(winAnimator, color);
335                }
336            }
337        }
338    };
339
340    private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment =
341            w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment);
342
343    private final Consumer<WindowState> mScheduleToastTimeout = w -> {
344        final int lostFocusUid = mTmpWindow.mOwnerUid;
345        final Handler handler = mService.mH;
346        if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
347            if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
348                handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
349                        w.mAttrs.hideTimeoutMilliseconds);
350            }
351        }
352    };
353
354    private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
355        final AppWindowToken focusedApp = mService.mFocusedApp;
356        if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
357                + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
358
359        if (!w.canReceiveKeys()) {
360            return false;
361        }
362
363        final AppWindowToken wtoken = w.mAppToken;
364
365        // If this window's application has been removed, just skip it.
366        if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
367            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
368                    + (wtoken.removed ? "removed" : "sendingToBottom"));
369            return false;
370        }
371
372        if (focusedApp == null) {
373            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
374                    + " using new focus @ " + w);
375            mTmpWindow = w;
376            return true;
377        }
378
379        if (!focusedApp.windowsAreFocusable()) {
380            // Current focused app windows aren't focusable...
381            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
382                    + " focusable using new focus @ " + w);
383            mTmpWindow = w;
384            return true;
385        }
386
387        // Descend through all of the app tokens and find the first that either matches
388        // win.mAppToken (return win) or mFocusedApp (return null).
389        if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
390            if (focusedApp.compareTo(wtoken) > 0) {
391                // App stack below focused app stack. No focus for you!!!
392                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
393                        "findFocusedWindow: Reached focused app=" + focusedApp);
394                mTmpWindow = null;
395                return true;
396            }
397        }
398
399        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
400        mTmpWindow = w;
401        return true;
402    };
403
404    private final Consumer<WindowState> mPrepareWindowSurfaces =
405            w -> w.mWinAnimator.prepareSurfaceLocked(true);
406
407    private final Consumer<WindowState> mPerformLayout = w -> {
408        // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
409        // wasting time and funky changes while a window is animating away.
410        final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
411                || w.isGoneForLayoutLw();
412
413        if (DEBUG_LAYOUT && !w.mLayoutAttached) {
414            Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
415                    + " mLayoutAttached=" + w.mLayoutAttached
416                    + " screen changed=" + w.isConfigChanged());
417            final AppWindowToken atoken = w.mAppToken;
418            if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
419                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
420                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
421                    + " parentHidden=" + w.isParentWindowHidden());
422            else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
423                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
424                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
425                    + " parentHidden=" + w.isParentWindowHidden());
426        }
427
428        // If this view is GONE, then skip it -- keep the current frame, and let the caller know
429        // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
430        // since that means "perform layout as normal, just don't display").
431        if (!gone || !w.mHaveFrame || w.mLayoutNeeded
432                || ((w.isConfigChanged() || w.setReportResizeHints())
433                && !w.isGoneForLayoutLw() &&
434                ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
435                        (w.mHasSurface && w.mAppToken != null &&
436                                w.mAppToken.layoutConfigChanges)))) {
437            if (!w.mLayoutAttached) {
438                if (mTmpInitial) {
439                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
440                    w.mContentChanged = false;
441                }
442                if (w.mAttrs.type == TYPE_DREAM) {
443                    // Don't layout windows behind a dream, so that if it does stuff like hide
444                    // the status bar we won't get a bad transition when it goes away.
445                    mTmpWindow = w;
446                }
447                w.mLayoutNeeded = false;
448                w.prelayout();
449                mService.mPolicy.layoutWindowLw(w, null);
450                w.mLayoutSeq = mService.mLayoutSeq;
451
452                // Window frames may have changed. Update dim layer with the new bounds.
453                final Task task = w.getTask();
454                if (task != null) {
455                    mDimLayerController.updateDimLayer(task);
456                }
457
458                if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
459                        + " mContainingFrame=" + w.mContainingFrame
460                        + " mDisplayFrame=" + w.mDisplayFrame);
461            }
462        }
463    };
464
465    private final Consumer<WindowState> mPerformLayoutAttached = w -> {
466        if (w.mLayoutAttached) {
467            if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
468                    + " mViewVisibility=" + w.mViewVisibility
469                    + " mRelayoutCalled=" + w.mRelayoutCalled);
470            // If this view is GONE, then skip it -- keep the current frame, and let the caller
471            // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
472            // windows, since that means "perform layout as normal, just don't display").
473            if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
474                return;
475            }
476            if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
477                    || w.mLayoutNeeded) {
478                if (mTmpInitial) {
479                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
480                    w.mContentChanged = false;
481                }
482                w.mLayoutNeeded = false;
483                w.prelayout();
484                mService.mPolicy.layoutWindowLw(w, w.getParentWindow());
485                w.mLayoutSeq = mService.mLayoutSeq;
486                if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
487                        + " mContainingFrame=" + w.mContainingFrame
488                        + " mDisplayFrame=" + w.mDisplayFrame);
489            }
490        } else if (w.mAttrs.type == TYPE_DREAM) {
491            // Don't layout windows behind a dream, so that if it does stuff like hide the
492            // status bar we won't get a bad transition when it goes away.
493            mTmpWindow = mTmpWindow2;
494        }
495    };
496
497    private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
498        if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
499                + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
500        return w.canBeImeTarget();
501    };
502
503    private final Consumer<WindowState> mApplyPostLayoutPolicy =
504            w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
505                    mService.mInputMethodTarget);
506
507    private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
508        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
509        final boolean obscuredChanged = w.mObscured !=
510                mTmpApplySurfaceChangesTransactionState.obscured;
511        final RootWindowContainer root = mService.mRoot;
512        // Only used if default window
513        final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
514
515        // Update effect.
516        w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
517        if (!mTmpApplySurfaceChangesTransactionState.obscured) {
518            final boolean isDisplayed = w.isDisplayedLw();
519
520            if (isDisplayed && w.isObscuringDisplay()) {
521                // This window completely covers everything behind it, so we want to leave all
522                // of them as undimmed (for performance reasons).
523                root.mObscuringWindow = w;
524                mTmpApplySurfaceChangesTransactionState.obscured = true;
525            }
526
527            mTmpApplySurfaceChangesTransactionState.displayHasContent |=
528                    root.handleNotObscuredLocked(w,
529                            mTmpApplySurfaceChangesTransactionState.obscured,
530                            mTmpApplySurfaceChangesTransactionState.syswin);
531
532            if (w.mHasSurface && isDisplayed) {
533                final int type = w.mAttrs.type;
534                if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
535                        || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
536                    mTmpApplySurfaceChangesTransactionState.syswin = true;
537                }
538                if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
539                        && w.mAttrs.preferredRefreshRate != 0) {
540                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
541                            = w.mAttrs.preferredRefreshRate;
542                }
543                if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
544                        && w.mAttrs.preferredDisplayModeId != 0) {
545                    mTmpApplySurfaceChangesTransactionState.preferredModeId
546                            = w.mAttrs.preferredDisplayModeId;
547                }
548            }
549        }
550
551        w.applyDimLayerIfNeeded();
552
553        if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
554                && mWallpaperController.isWallpaperTarget(w)) {
555            // This is the wallpaper target and its obscured state changed... make sure the
556            // current wallpaper's visibility has been updated accordingly.
557            mWallpaperController.updateWallpaperVisibility();
558        }
559
560        w.handleWindowMovedIfNeeded();
561
562        final WindowStateAnimator winAnimator = w.mWinAnimator;
563
564        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
565        w.mContentChanged = false;
566
567        // Moved from updateWindowsAndWallpaperLocked().
568        if (w.mHasSurface) {
569            // Take care of the window being ready to display.
570            final boolean committed = winAnimator.commitFinishDrawingLocked();
571            if (isDefaultDisplay && committed) {
572                if (w.mAttrs.type == TYPE_DREAM) {
573                    // HACK: When a dream is shown, it may at that point hide the lock screen.
574                    // So we need to redo the layout to let the phone window manager make this
575                    // happen.
576                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
577                    if (DEBUG_LAYOUT_REPEATS) {
578                        surfacePlacer.debugLayoutRepeats(
579                                "dream and commitFinishDrawingLocked true",
580                                pendingLayoutChanges);
581                    }
582                }
583                if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
584                    if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
585                            "First draw done in potential wallpaper target " + w);
586                    root.mWallpaperMayChange = true;
587                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
588                    if (DEBUG_LAYOUT_REPEATS) {
589                        surfacePlacer.debugLayoutRepeats(
590                                "wallpaper and commitFinishDrawingLocked true",
591                                pendingLayoutChanges);
592                    }
593                }
594            }
595            if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
596                // Updates the shown frame before we set up the surface. This is needed
597                // because the resizing could change the top-left position (in addition to
598                // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
599                // position the surface.
600                //
601                // If an animation is being started, we can't call this method because the
602                // animation hasn't processed its initial transformation yet, but in general
603                // we do want to update the position if the window is animating.
604                winAnimator.computeShownFrameLocked();
605            }
606            winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
607        }
608
609        final AppWindowToken atoken = w.mAppToken;
610        if (atoken != null) {
611            final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
612            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
613                mTmpUpdateAllDrawn.add(atoken);
614            }
615        }
616
617        if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
618                && w.isDisplayedLw()) {
619            mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
620        }
621
622        w.updateResizingWindowIfNeeded();
623    };
624
625    /**
626     * @param display May not be null.
627     * @param service You know.
628     * @param layersController window layer controller used to assign layer to the windows on this
629     *                         display.
630     * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
631     *                            wallpaper windows in the window list.
632     */
633    DisplayContent(Display display, WindowManagerService service,
634            WindowLayersController layersController, WallpaperController wallpaperController) {
635        mDisplay = display;
636        mDisplayId = display.getDisplayId();
637        mLayersController = layersController;
638        mWallpaperController = wallpaperController;
639        display.getDisplayInfo(mDisplayInfo);
640        display.getMetrics(mDisplayMetrics);
641        isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
642        mService = service;
643        initializeDisplayBaseInfo();
644        mDividerControllerLocked = new DockedStackDividerController(service, this);
645        mPinnedStackControllerLocked = new PinnedStackController(service, this);
646        mDimLayerController = new DimLayerController(this);
647
648        // These are the only direct children we should ever have and they are permanent.
649        super.addChild(mBelowAppWindowsContainers, null);
650        super.addChild(mTaskStackContainers, null);
651        super.addChild(mAboveAppWindowsContainers, null);
652        super.addChild(mImeWindowsContainers, null);
653    }
654
655    int getDisplayId() {
656        return mDisplayId;
657    }
658
659    WindowToken getWindowToken(IBinder binder) {
660        return mTokenMap.get(binder);
661    }
662
663    AppWindowToken getAppWindowToken(IBinder binder) {
664        final WindowToken token = getWindowToken(binder);
665        if (token == null) {
666            return null;
667        }
668        return token.asAppWindowToken();
669    }
670
671    void addWindowToken(IBinder binder, WindowToken token) {
672        final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
673        if (dc != null) {
674            // We currently don't support adding a window token to the display if the display
675            // already has the binder mapped to another token. If there is a use case for supporting
676            // this moving forward we will either need to merge the WindowTokens some how or have
677            // the binder map to a list of window tokens.
678            throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
679                    + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
680        }
681        mTokenMap.put(binder, token);
682
683        if (token.asAppWindowToken() == null) {
684            // Add non-app token to container hierarchy on the display. App tokens are added through
685            // the parent container managing them (e.g. Tasks).
686            switch (token.windowType) {
687                case TYPE_WALLPAPER:
688                    mBelowAppWindowsContainers.addChild(token);
689                    break;
690                case TYPE_INPUT_METHOD:
691                case TYPE_INPUT_METHOD_DIALOG:
692                    mImeWindowsContainers.addChild(token);
693                    break;
694                default:
695                    mAboveAppWindowsContainers.addChild(token);
696                    break;
697            }
698        }
699    }
700
701    WindowToken removeWindowToken(IBinder binder) {
702        final WindowToken token = mTokenMap.remove(binder);
703        if (token != null && token.asAppWindowToken() == null) {
704            token.setExiting();
705        }
706        return token;
707    }
708
709    /** Changes the display the input window token is housed on to this one. */
710    void reParentWindowToken(WindowToken token) {
711        final DisplayContent prevDc = token.getDisplayContent();
712        if (prevDc == this) {
713            return;
714        }
715        if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null) {
716            switch (token.windowType) {
717                case TYPE_WALLPAPER:
718                    prevDc.mBelowAppWindowsContainers.removeChild(token);
719                    break;
720                case TYPE_INPUT_METHOD:
721                case TYPE_INPUT_METHOD_DIALOG:
722                    prevDc.mImeWindowsContainers.removeChild(token);
723                    break;
724                default:
725                    prevDc.mAboveAppWindowsContainers.removeChild(token);
726                    break;
727            }
728        }
729
730        addWindowToken(token.token, token);
731    }
732
733    void removeAppToken(IBinder binder) {
734        final WindowToken token = removeWindowToken(binder);
735        if (token == null) {
736            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
737            return;
738        }
739
740        final AppWindowToken appToken = token.asAppWindowToken();
741
742        if (appToken == null) {
743            Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
744            return;
745        }
746
747        appToken.onRemovedFromDisplay();
748    }
749
750    Display getDisplay() {
751        return mDisplay;
752    }
753
754    DisplayInfo getDisplayInfo() {
755        return mDisplayInfo;
756    }
757
758    DisplayMetrics getDisplayMetrics() {
759        return mDisplayMetrics;
760    }
761
762    DockedStackDividerController getDockedDividerController() {
763        return mDividerControllerLocked;
764    }
765
766    PinnedStackController getPinnedStackController() {
767        return mPinnedStackControllerLocked;
768    }
769
770    /**
771     * Returns true if the specified UID has access to this display.
772     */
773    boolean hasAccess(int uid) {
774        return mDisplay.hasAccess(uid);
775    }
776
777    boolean isPrivate() {
778        return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
779    }
780
781    TaskStack getHomeStack() {
782        if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
783            Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
784        }
785        return mHomeStack;
786    }
787
788    TaskStack getStackById(int stackId) {
789        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
790            final TaskStack stack = mTaskStackContainers.get(i);
791            if (stack.mStackId == stackId) {
792                return stack;
793            }
794        }
795        return null;
796    }
797
798    @Override
799    void onConfigurationChanged(Configuration newParentConfig) {
800        super.onConfigurationChanged(newParentConfig);
801
802        // The display size information is heavily dependent on the resources in the current
803        // configuration, so we need to reconfigure it every time the configuration changes.
804        // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
805        mService.reconfigureDisplayLocked(this);
806
807        getDockedDividerController().onConfigurationChanged();
808        getPinnedStackController().onConfigurationChanged();
809    }
810
811    /**
812     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
813     * bounds were updated.
814     */
815    void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
816        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
817            final TaskStack stack = mTaskStackContainers.get(i);
818            if (stack.updateBoundsAfterConfigChange()) {
819                changedStackList.add(stack.mStackId);
820            }
821        }
822    }
823
824    @Override
825    boolean fillsParent() {
826        return true;
827    }
828
829    @Override
830    boolean isVisible() {
831        return true;
832    }
833
834    @Override
835    void onAppTransitionDone() {
836        super.onAppTransitionDone();
837        mService.mWindowsChanged = true;
838    }
839
840    @Override
841    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
842        // Special handling so we can process IME windows with #forAllImeWindows above their IME
843        // target, or here in order if there isn't an IME target.
844        if (traverseTopToBottom) {
845            for (int i = mChildren.size() - 1; i >= 0; --i) {
846                final DisplayChildWindowContainer child = mChildren.get(i);
847                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
848                    // In this case the Ime windows will be processed above their target so we skip
849                    // here.
850                    continue;
851                }
852                if (child.forAllWindows(callback, traverseTopToBottom)) {
853                    return true;
854                }
855            }
856        } else {
857            final int count = mChildren.size();
858            for (int i = 0; i < count; i++) {
859                final DisplayChildWindowContainer child = mChildren.get(i);
860                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
861                    // In this case the Ime windows will be processed above their target so we skip
862                    // here.
863                    continue;
864                }
865                if (child.forAllWindows(callback, traverseTopToBottom)) {
866                    return true;
867                }
868            }
869        }
870        return false;
871    }
872
873    boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
874        return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
875    }
876
877    @Override
878    int getOrientation() {
879        final WindowManagerPolicy policy = mService.mPolicy;
880
881        if (mService.mDisplayFrozen) {
882            if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
883                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
884                        "Display is frozen, return " + mService.mLastWindowForcedOrientation);
885                // If the display is frozen, some activities may be in the middle of restarting, and
886                // thus have removed their old window. If the window has the flag to hide the lock
887                // screen, then the lock screen can re-appear and inflict its own orientation on us.
888                // Keep the orientation stable until this all settles down.
889                return mService.mLastWindowForcedOrientation;
890            } else if (policy.isKeyguardLocked()) {
891                // Use the last orientation the while the display is frozen with the keyguard
892                // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
893                // window. We don't want to check the show when locked window directly though as
894                // things aren't stable while the display is frozen, for example the window could be
895                // momentarily unavailable due to activity relaunch.
896                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
897                        + "return " + mService.mLastOrientation);
898                return mService.mLastOrientation;
899            }
900        } else {
901            final int orientation = mAboveAppWindowsContainers.getOrientation();
902            if (orientation != SCREEN_ORIENTATION_UNSET) {
903                return orientation;
904            }
905        }
906
907        // Top system windows are not requesting an orientation. Start searching from apps.
908        return mTaskStackContainers.getOrientation();
909    }
910
911    void updateDisplayInfo() {
912        mDisplay.getDisplayInfo(mDisplayInfo);
913        mDisplay.getMetrics(mDisplayMetrics);
914        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
915            mTaskStackContainers.get(i).updateDisplayInfo(null);
916        }
917    }
918
919    void initializeDisplayBaseInfo() {
920        final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
921        if (displayManagerInternal != null) {
922            // Bootstrap the default logical display from the display manager.
923            final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
924            if (newDisplayInfo != null) {
925                mDisplayInfo.copyFrom(newDisplayInfo);
926            }
927        }
928
929        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
930        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
931        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
932        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
933    }
934
935    void getLogicalDisplayRect(Rect out) {
936        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
937        final int orientation = mDisplayInfo.rotation;
938        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
939        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
940        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
941        int width = mDisplayInfo.logicalWidth;
942        int left = (physWidth - width) / 2;
943        int height = mDisplayInfo.logicalHeight;
944        int top = (physHeight - height) / 2;
945        out.set(left, top, left + width, top + height);
946    }
947
948    private void getLogicalDisplayRect(Rect out, int orientation) {
949        getLogicalDisplayRect(out);
950
951        // Rotate the Rect if needed.
952        final int currentRotation = mDisplayInfo.rotation;
953        final int rotationDelta = deltaRotation(currentRotation, orientation);
954        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
955            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
956            mTmpRectF.set(out);
957            mTmpMatrix.mapRect(mTmpRectF);
958            mTmpRectF.round(out);
959        }
960    }
961
962    void getContentRect(Rect out) {
963        out.set(mContentRect);
964    }
965
966    /**
967     * Adds the stack to this display.
968     * @see WindowManagerService#addStackToDisplay(int, int, boolean)
969     */
970    Rect addStackToDisplay(int stackId, boolean onTop) {
971        boolean attachedToDisplay = false;
972        TaskStack stack = mService.mStackIdToStack.get(stackId);
973        if (stack == null) {
974            if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
975                    + mDisplayId);
976
977            stack = getStackById(stackId);
978            if (stack != null) {
979                // It's already attached to the display...clear mDeferRemoval and move stack to
980                // appropriate z-order on display as needed.
981                stack.mDeferRemoval = false;
982                moveStack(stack, onTop);
983                attachedToDisplay = true;
984            } else {
985                stack = new TaskStack(mService, stackId);
986            }
987
988            mService.mStackIdToStack.put(stackId, stack);
989            if (stackId == DOCKED_STACK_ID) {
990                mDividerControllerLocked.notifyDockedStackExistsChanged(true);
991            }
992        } else {
993            final DisplayContent currentDC = stack.getDisplayContent();
994            if (currentDC != null) {
995                throw new IllegalStateException("Trying to add stackId=" + stackId
996                        + "to displayId=" + mDisplayId + ", but it's already attached to displayId="
997                        + currentDC.getDisplayId());
998            }
999        }
1000
1001        if (!attachedToDisplay) {
1002            mTaskStackContainers.addStackToDisplay(stack, onTop);
1003        }
1004
1005        if (stack.getRawFullscreen()) {
1006            return null;
1007        }
1008        final Rect bounds = new Rect();
1009        stack.getRawBounds(bounds);
1010        return bounds;
1011    }
1012
1013    /** Removes the stack from the display and prepares for changing the parent. */
1014    private void removeStackFromDisplay(TaskStack stack) {
1015        mTaskStackContainers.removeStackFromDisplay(stack);
1016    }
1017
1018    /** Moves the stack to this display and returns the updated bounds. */
1019    Rect moveStackToDisplay(TaskStack stack) {
1020        final DisplayContent currentDisplayContent = stack.getDisplayContent();
1021        if (currentDisplayContent == null) {
1022            throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
1023                    + " which is not currently attached to any display");
1024        }
1025        if (stack.getDisplayContent().getDisplayId() == mDisplayId) {
1026            throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
1027                    + " to its current displayId=" + mDisplayId);
1028        }
1029
1030        currentDisplayContent.removeStackFromDisplay(stack);
1031        return addStackToDisplay(stack.mStackId, true /* onTop */);
1032    }
1033
1034    void moveStack(TaskStack stack, boolean toTop) {
1035        mTaskStackContainers.moveStack(stack, toTop);
1036    }
1037
1038    @Override
1039    protected void addChild(DisplayChildWindowContainer child,
1040            Comparator<DisplayChildWindowContainer> comparator) {
1041        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1042    }
1043
1044    @Override
1045    protected void addChild(DisplayChildWindowContainer child, int index) {
1046        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1047    }
1048
1049    @Override
1050    protected void removeChild(DisplayChildWindowContainer child) {
1051        // Only allow removal of direct children from this display if the display is in the process
1052        // of been removed.
1053        if (mRemovingDisplay) {
1054            super.removeChild(child);
1055            return;
1056        }
1057        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1058    }
1059
1060    int taskIdFromPoint(int x, int y) {
1061        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1062            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1063            final int taskId = stack.taskIdFromPoint(x, y);
1064            if (taskId != -1) {
1065                return taskId;
1066            }
1067        }
1068        return -1;
1069    }
1070
1071    /**
1072     * Find the task whose outside touch area (for resizing) (x, y) falls within.
1073     * Returns null if the touch doesn't fall into a resizing area.
1074     */
1075    Task findTaskForResizePoint(int x, int y) {
1076        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
1077        mTmpTaskForResizePointSearchResult.reset();
1078        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1079            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1080            if (!StackId.isTaskResizeAllowed(stack.mStackId)) {
1081                return null;
1082            }
1083
1084            stack.findTaskForResizePoint(x, y, delta, mTmpTaskForResizePointSearchResult);
1085            if (mTmpTaskForResizePointSearchResult.searchDone) {
1086                return mTmpTaskForResizePointSearchResult.taskForResize;
1087            }
1088        }
1089        return null;
1090    }
1091
1092    void setTouchExcludeRegion(Task focusedTask) {
1093        mTouchExcludeRegion.set(mBaseDisplayRect);
1094        final int delta = dipToPixel(RESIZE_HANDLE_WIDTH_IN_DP, mDisplayMetrics);
1095        mTmpRect2.setEmpty();
1096        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1097            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1098            stack.setTouchExcludeRegion(
1099                    focusedTask, delta, mTouchExcludeRegion, mContentRect, mTmpRect2);
1100        }
1101        // If we removed the focused task above, add it back and only leave its
1102        // outside touch area in the exclusion. TapDectector is not interested in
1103        // any touch inside the focused task itself.
1104        if (!mTmpRect2.isEmpty()) {
1105            mTouchExcludeRegion.op(mTmpRect2, Region.Op.UNION);
1106        }
1107        final WindowState inputMethod = mService.mInputMethodWindow;
1108        if (inputMethod != null && inputMethod.isVisibleLw()) {
1109            // If the input method is visible and the user is typing, we don't want these touch
1110            // events to be intercepted and used to change focus. This would likely cause a
1111            // disappearance of the input method.
1112            inputMethod.getTouchableRegion(mTmpRegion);
1113            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
1114        }
1115        for (int i = mTapExcludedWindows.size() - 1; i >= 0; i--) {
1116            WindowState win = mTapExcludedWindows.get(i);
1117            win.getTouchableRegion(mTmpRegion);
1118            mTouchExcludeRegion.op(mTmpRegion, Region.Op.UNION);
1119        }
1120        // TODO(multi-display): Support docked stacks on secondary displays.
1121        if (mDisplayId == DEFAULT_DISPLAY && getDockedStackLocked() != null) {
1122            mDividerControllerLocked.getTouchRegion(mTmpRect);
1123            mTmpRegion.set(mTmpRect);
1124            mTouchExcludeRegion.op(mTmpRegion, Op.UNION);
1125        }
1126        if (mTapDetector != null) {
1127            mTapDetector.setTouchExcludeRegion(mTouchExcludeRegion);
1128        }
1129    }
1130
1131    @Override
1132    void switchUser() {
1133        super.switchUser();
1134        mService.mWindowsChanged = true;
1135    }
1136
1137    private void resetAnimationBackgroundAnimator() {
1138        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1139            mTaskStackContainers.get(stackNdx).resetAnimationBackgroundAnimator();
1140        }
1141    }
1142
1143    boolean animateDimLayers() {
1144        return mDimLayerController.animateDimLayers();
1145    }
1146
1147    private void resetDimming() {
1148        mDimLayerController.resetDimming();
1149    }
1150
1151    boolean isDimming() {
1152        return mDimLayerController.isDimming();
1153    }
1154
1155    private void stopDimmingIfNeeded() {
1156        mDimLayerController.stopDimmingIfNeeded();
1157    }
1158
1159    @Override
1160    void removeIfPossible() {
1161        if (isAnimating()) {
1162            mDeferredRemoval = true;
1163            return;
1164        }
1165        removeImmediately();
1166    }
1167
1168    @Override
1169    void removeImmediately() {
1170        mRemovingDisplay = true;
1171        try {
1172            super.removeImmediately();
1173            if (DEBUG_DISPLAY) Slog.v(TAG_WM, "Removing display=" + this);
1174            mDimLayerController.close();
1175            if (mDisplayId == DEFAULT_DISPLAY) {
1176                mService.unregisterPointerEventListener(mTapDetector);
1177                mService.unregisterPointerEventListener(mService.mMousePositionTracker);
1178            }
1179        } finally {
1180            mRemovingDisplay = false;
1181        }
1182    }
1183
1184    /** Returns true if a removal action is still being deferred. */
1185    @Override
1186    boolean checkCompleteDeferredRemoval() {
1187        final boolean stillDeferringRemoval = super.checkCompleteDeferredRemoval();
1188
1189        if (!stillDeferringRemoval && mDeferredRemoval) {
1190            removeImmediately();
1191            mService.onDisplayRemoved(mDisplayId);
1192            return false;
1193        }
1194        return true;
1195    }
1196
1197    boolean animateForIme(float interpolatedValue, float animationTarget,
1198            float dividerAnimationTarget) {
1199        boolean updated = false;
1200
1201        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1202            final TaskStack stack = mTaskStackContainers.get(i);
1203            if (stack == null || !stack.isAdjustedForIme()) {
1204                continue;
1205            }
1206
1207            if (interpolatedValue >= 1f && animationTarget == 0f && dividerAnimationTarget == 0f) {
1208                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
1209                updated = true;
1210            } else {
1211                mDividerControllerLocked.mLastAnimationProgress =
1212                        mDividerControllerLocked.getInterpolatedAnimationValue(interpolatedValue);
1213                mDividerControllerLocked.mLastDividerProgress =
1214                        mDividerControllerLocked.getInterpolatedDividerValue(interpolatedValue);
1215                updated |= stack.updateAdjustForIme(
1216                        mDividerControllerLocked.mLastAnimationProgress,
1217                        mDividerControllerLocked.mLastDividerProgress,
1218                        false /* force */);
1219            }
1220            if (interpolatedValue >= 1f) {
1221                stack.endImeAdjustAnimation();
1222            }
1223        }
1224
1225        return updated;
1226    }
1227
1228    boolean clearImeAdjustAnimation() {
1229        boolean changed = false;
1230        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1231            final TaskStack stack = mTaskStackContainers.get(i);
1232            if (stack != null && stack.isAdjustedForIme()) {
1233                stack.resetAdjustedForIme(true /* adjustBoundsNow */);
1234                changed  = true;
1235            }
1236        }
1237        return changed;
1238    }
1239
1240    void beginImeAdjustAnimation() {
1241        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1242            final TaskStack stack = mTaskStackContainers.get(i);
1243            if (stack.isVisible() && stack.isAdjustedForIme()) {
1244                stack.beginImeAdjustAnimation();
1245            }
1246        }
1247    }
1248
1249    void adjustForImeIfNeeded() {
1250        final WindowState imeWin = mService.mInputMethodWindow;
1251        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
1252                && !mDividerControllerLocked.isImeHideRequested();
1253        final boolean dockVisible = mService.isStackVisibleLocked(DOCKED_STACK_ID);
1254        final TaskStack imeTargetStack = mService.getImeFocusStackLocked();
1255        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
1256                imeTargetStack.getDockSide() : DOCKED_INVALID;
1257        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
1258        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
1259        final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock();
1260        final int imeHeight = mService.mPolicy.getInputMethodWindowVisibleHeightLw();
1261        final boolean imeHeightChanged = imeVisible &&
1262                imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
1263
1264        // The divider could be adjusted for IME position, or be thinner than usual,
1265        // or both. There are three possible cases:
1266        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
1267        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
1268        // - If IME is not visible, divider is not moved and is normal width.
1269
1270        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
1271            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1272                final TaskStack stack = mTaskStackContainers.get(i);
1273                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
1274                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)) {
1275                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
1276                } else {
1277                    stack.resetAdjustedForIme(false);
1278                }
1279            }
1280            mDividerControllerLocked.setAdjustedForIme(
1281                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
1282        } else {
1283            for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
1284                final TaskStack stack = mTaskStackContainers.get(i);
1285                stack.resetAdjustedForIme(!dockVisible);
1286            }
1287            mDividerControllerLocked.setAdjustedForIme(
1288                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
1289        }
1290        mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
1291    }
1292
1293    void setInputMethodAnimLayerAdjustment(int adj) {
1294        if (DEBUG_LAYERS) Slog.v(TAG_WM, "Setting im layer adj to " + adj);
1295        mInputMethodAnimLayerAdjustment = adj;
1296        mImeWindowsContainers.forAllWindows(mSetInputMethodAnimLayerAdjustment,
1297                true /* traverseTopToBottom */);
1298    }
1299
1300    /**
1301     * If a window that has an animation specifying a colored background and the current wallpaper
1302     * is visible, then the color goes *below* the wallpaper so we don't cause the wallpaper to
1303     * suddenly disappear.
1304     */
1305    int getLayerForAnimationBackground(WindowStateAnimator winAnimator) {
1306        final WindowState visibleWallpaper = mBelowAppWindowsContainers.getWindow(
1307                w -> w.mIsWallpaper && w.isVisibleNow());
1308
1309        if (visibleWallpaper != null) {
1310            return visibleWallpaper.mWinAnimator.mAnimLayer;
1311        }
1312        return winAnimator.mAnimLayer;
1313    }
1314
1315    void prepareFreezingTaskBounds() {
1316        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1317            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1318            stack.prepareFreezingTaskBounds();
1319        }
1320    }
1321
1322    void rotateBounds(int oldRotation, int newRotation, Rect bounds) {
1323        getLogicalDisplayRect(mTmpRect, newRotation);
1324
1325        // Compute a transform matrix to undo the coordinate space transformation,
1326        // and present the window at the same physical position it previously occupied.
1327        final int deltaRotation = deltaRotation(newRotation, oldRotation);
1328        createRotationMatrix(deltaRotation, mTmpRect.width(), mTmpRect.height(), mTmpMatrix);
1329
1330        mTmpRectF.set(bounds);
1331        mTmpMatrix.mapRect(mTmpRectF);
1332        mTmpRectF.round(bounds);
1333    }
1334
1335    static int deltaRotation(int oldRotation, int newRotation) {
1336        int delta = newRotation - oldRotation;
1337        if (delta < 0) delta += 4;
1338        return delta;
1339    }
1340
1341    private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight,
1342            Matrix outMatrix) {
1343        // For rotations without Z-ordering we don't need the target rectangle's position.
1344        createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth,
1345                displayHeight, outMatrix);
1346    }
1347
1348    static void createRotationMatrix(int rotation, float rectLeft, float rectTop,
1349            float displayWidth, float displayHeight, Matrix outMatrix) {
1350        switch (rotation) {
1351            case ROTATION_0:
1352                outMatrix.reset();
1353                break;
1354            case ROTATION_270:
1355                outMatrix.setRotate(270, 0, 0);
1356                outMatrix.postTranslate(0, displayHeight);
1357                outMatrix.postTranslate(rectTop, 0);
1358                break;
1359            case ROTATION_180:
1360                outMatrix.reset();
1361                break;
1362            case ROTATION_90:
1363                outMatrix.setRotate(90, 0, 0);
1364                outMatrix.postTranslate(displayWidth, 0);
1365                outMatrix.postTranslate(-rectTop, rectLeft);
1366                break;
1367        }
1368    }
1369
1370    public void dump(String prefix, PrintWriter pw) {
1371        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
1372        final String subPrefix = "  " + prefix;
1373        pw.print(subPrefix); pw.print("init="); pw.print(mInitialDisplayWidth); pw.print("x");
1374            pw.print(mInitialDisplayHeight); pw.print(" "); pw.print(mInitialDisplayDensity);
1375            pw.print("dpi");
1376            if (mInitialDisplayWidth != mBaseDisplayWidth
1377                    || mInitialDisplayHeight != mBaseDisplayHeight
1378                    || mInitialDisplayDensity != mBaseDisplayDensity) {
1379                pw.print(" base=");
1380                pw.print(mBaseDisplayWidth); pw.print("x"); pw.print(mBaseDisplayHeight);
1381                pw.print(" "); pw.print(mBaseDisplayDensity); pw.print("dpi");
1382            }
1383            if (mDisplayScalingDisabled) {
1384                pw.println(" noscale");
1385            }
1386            pw.print(" cur=");
1387            pw.print(mDisplayInfo.logicalWidth);
1388            pw.print("x"); pw.print(mDisplayInfo.logicalHeight);
1389            pw.print(" app=");
1390            pw.print(mDisplayInfo.appWidth);
1391            pw.print("x"); pw.print(mDisplayInfo.appHeight);
1392            pw.print(" rng="); pw.print(mDisplayInfo.smallestNominalAppWidth);
1393            pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
1394            pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
1395            pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
1396            pw.println(subPrefix + "deferred=" + mDeferredRemoval
1397                    + " mLayoutNeeded=" + mLayoutNeeded);
1398
1399        pw.println();
1400        pw.println(prefix + "Application tokens in top down Z order:");
1401        for (int stackNdx = mTaskStackContainers.size() - 1; stackNdx >= 0; --stackNdx) {
1402            final TaskStack stack = mTaskStackContainers.get(stackNdx);
1403            stack.dump(prefix + "  ", pw);
1404        }
1405
1406        pw.println();
1407        if (!mExitingTokens.isEmpty()) {
1408            pw.println();
1409            pw.println("  Exiting tokens:");
1410            for (int i = mExitingTokens.size() - 1; i >= 0; i--) {
1411                final WindowToken token = mExitingTokens.get(i);
1412                pw.print("  Exiting #"); pw.print(i);
1413                pw.print(' '); pw.print(token);
1414                pw.println(':');
1415                token.dump(pw, "    ");
1416            }
1417        }
1418        pw.println();
1419        mDimLayerController.dump(prefix, pw);
1420        pw.println();
1421        mDividerControllerLocked.dump(prefix, pw);
1422        pw.println();
1423        mPinnedStackControllerLocked.dump(prefix, pw);
1424
1425        if (mInputMethodAnimLayerAdjustment != 0) {
1426            pw.println(subPrefix
1427                    + "mInputMethodAnimLayerAdjustment=" + mInputMethodAnimLayerAdjustment);
1428        }
1429    }
1430
1431    @Override
1432    public String toString() {
1433        return "Display " + mDisplayId + " info=" + mDisplayInfo + " stacks=" + mChildren;
1434    }
1435
1436    String getName() {
1437        return "Display " + mDisplayId + " name=\"" + mDisplayInfo.name + "\"";
1438    }
1439
1440    /**
1441     * @return The docked stack, but only if it is visible, and {@code null} otherwise.
1442     */
1443    TaskStack getDockedStackLocked() {
1444        final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
1445        return (stack != null && stack.isVisible()) ? stack : null;
1446    }
1447
1448    /**
1449     * Like {@link #getDockedStackLocked}, but also returns the docked stack if it's currently not
1450     * visible.
1451     */
1452    TaskStack getDockedStackIgnoringVisibility() {
1453        return mService.mStackIdToStack.get(DOCKED_STACK_ID);
1454    }
1455
1456    /** Find the visible, touch-deliverable window under the given point */
1457    WindowState getTouchableWinAtPointLocked(float xf, float yf) {
1458        final int x = (int) xf;
1459        final int y = (int) yf;
1460        final WindowState touchedWin = getWindow(w -> {
1461            final int flags = w.mAttrs.flags;
1462            if (!w.isVisibleLw()) {
1463                return false;
1464            }
1465            if ((flags & FLAG_NOT_TOUCHABLE) != 0) {
1466                return false;
1467            }
1468
1469            w.getVisibleBounds(mTmpRect);
1470            if (!mTmpRect.contains(x, y)) {
1471                return false;
1472            }
1473
1474            w.getTouchableRegion(mTmpRegion);
1475
1476            final int touchFlags = flags & (FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL);
1477            return mTmpRegion.contains(x, y) || touchFlags == 0;
1478        });
1479
1480        return touchedWin;
1481    }
1482
1483    boolean canAddToastWindowForUid(int uid) {
1484        // We allow one toast window per UID being shown at a time.
1485        final WindowState win = getWindow(w ->
1486                w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == uid && !w.mPermanentlyHidden
1487                && !w.mWindowRemovalAllowed);
1488        return win == null;
1489    }
1490
1491    void scheduleToastWindowsTimeoutIfNeededLocked(WindowState oldFocus, WindowState newFocus) {
1492        if (oldFocus == null || (newFocus != null && newFocus.mOwnerUid == oldFocus.mOwnerUid)) {
1493            return;
1494        }
1495
1496        // Used to communicate the old focus to the callback method.
1497        mTmpWindow = oldFocus;
1498
1499        forAllWindows(mScheduleToastTimeout, false /* traverseTopToBottom */);
1500    }
1501
1502    WindowState findFocusedWindow() {
1503        mTmpWindow = null;
1504
1505        forAllWindows(mFindFocusedWindow, true /* traverseTopToBottom */);
1506
1507        if (mTmpWindow == null) {
1508            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: No focusable windows.");
1509            return null;
1510        }
1511        return mTmpWindow;
1512    }
1513
1514    /** Updates the layer assignment of windows on this display. */
1515    void assignWindowLayers(boolean setLayoutNeeded) {
1516        mLayersController.assignWindowLayers(this);
1517        if (setLayoutNeeded) {
1518            setLayoutNeeded();
1519        }
1520    }
1521
1522    void layoutAndAssignWindowLayersIfNeeded() {
1523        mService.mWindowsChanged = true;
1524        setLayoutNeeded();
1525
1526        if (!mService.updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
1527                false /*updateInputWindows*/)) {
1528            assignWindowLayers(false /* setLayoutNeeded */);
1529        }
1530
1531        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
1532        mService.mWindowPlacerLocked.performSurfacePlacement();
1533        mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
1534    }
1535
1536    /** Returns true if a leaked surface was destroyed */
1537    boolean destroyLeakedSurfaces() {
1538        // Used to indicate that a surface was leaked.
1539        mTmpWindow = null;
1540        forAllWindows(w -> {
1541            final WindowStateAnimator wsa = w.mWinAnimator;
1542            if (wsa.mSurfaceController == null) {
1543                return;
1544            }
1545            if (!mService.mSessions.contains(wsa.mSession)) {
1546                Slog.w(TAG_WM, "LEAKED SURFACE (session doesn't exist): "
1547                        + w + " surface=" + wsa.mSurfaceController
1548                        + " token=" + w.mToken
1549                        + " pid=" + w.mSession.mPid
1550                        + " uid=" + w.mSession.mUid);
1551                wsa.destroySurface();
1552                mService.mForceRemoves.add(w);
1553                mTmpWindow = w;
1554            } else if (w.mAppToken != null && w.mAppToken.clientHidden) {
1555                Slog.w(TAG_WM, "LEAKED SURFACE (app token hidden): "
1556                        + w + " surface=" + wsa.mSurfaceController
1557                        + " token=" + w.mAppToken
1558                        + " saved=" + w.hasSavedSurface());
1559                if (SHOW_TRANSACTIONS) logSurface(w, "LEAK DESTROY", false);
1560                wsa.destroySurface();
1561                mTmpWindow = w;
1562            }
1563        }, false /* traverseTopToBottom */);
1564
1565        return mTmpWindow != null;
1566    }
1567
1568    /**
1569     * Determine and return the window that should be the IME target.
1570     * @param updateImeTarget If true the system IME target will be updated to match what we found.
1571     * @return The window that should be used as the IME target or null if there isn't any.
1572     */
1573    WindowState computeImeTarget(boolean updateImeTarget) {
1574        if (mService.mInputMethodWindow == null) {
1575            // There isn't an IME so there shouldn't be a target...That was easy!
1576            if (updateImeTarget) {
1577                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from "
1578                        + mService.mInputMethodTarget + " to null since mInputMethodWindow is null");
1579                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
1580            }
1581            return null;
1582        }
1583
1584        // TODO(multidisplay): Needs some serious rethought when the target and IME are not on the
1585        // same display. Or even when the current IME/target are not on the same screen as the next
1586        // IME/target. For now only look for input windows on the main screen.
1587        mUpdateImeTarget = updateImeTarget;
1588        WindowState target = getWindow(mComputeImeTargetPredicate);
1589
1590
1591        // Yet more tricksyness!  If this window is a "starting" window, we do actually want
1592        // to be on top of it, but it is not -really- where input will go. So look down below
1593        // for a real window to target...
1594        if (target != null && target.mAttrs.type == TYPE_APPLICATION_STARTING) {
1595            final AppWindowToken token = target.mAppToken;
1596            if (token != null) {
1597                final WindowState betterTarget = token.getImeTargetBelowWindow(target);
1598                if (betterTarget != null) {
1599                    target = betterTarget;
1600                }
1601            }
1602        }
1603
1604        if (DEBUG_INPUT_METHOD && updateImeTarget) Slog.v(TAG_WM,
1605                "Proposed new IME target: " + target);
1606
1607        // Now, a special case -- if the last target's window is in the process of exiting, and is
1608        // above the new target, keep on the last target to avoid flicker. Consider for example a
1609        // Dialog with the IME shown: when the Dialog is dismissed, we want to keep the IME above it
1610        // until it is completely gone so it doesn't drop behind the dialog or its full-screen
1611        // scrim.
1612        final WindowState curTarget = mService.mInputMethodTarget;
1613        if (curTarget != null && curTarget.isDisplayedLw() && curTarget.isClosing()
1614                && (target == null
1615                    || curTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer)) {
1616            if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Current target higher, not changing");
1617            return curTarget;
1618        }
1619
1620        if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, "Desired input method target=" + target
1621                + " updateImeTarget=" + updateImeTarget);
1622
1623        if (target == null) {
1624            if (updateImeTarget) {
1625                if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget
1626                        + " to null." + (SHOW_STACK_CRAWLS ? " Callers="
1627                        + Debug.getCallers(4) : ""));
1628                setInputMethodTarget(null, mService.mInputMethodTargetWaitingAnim, 0);
1629            }
1630
1631            return null;
1632        }
1633
1634        if (updateImeTarget) {
1635            AppWindowToken token = curTarget == null ? null : curTarget.mAppToken;
1636            if (token != null) {
1637
1638                // Now some fun for dealing with window animations that modify the Z order. We need
1639                // to look at all windows below the current target that are in this app, finding the
1640                // highest visible one in layering.
1641                WindowState highestTarget = null;
1642                if (token.mAppAnimator.animating || token.mAppAnimator.animation != null) {
1643                    highestTarget = token.getHighestAnimLayerWindow(curTarget);
1644                }
1645
1646                if (highestTarget != null) {
1647                    final AppTransition appTransition = mService.mAppTransition;
1648                    if (DEBUG_INPUT_METHOD) Slog.v(TAG_WM, appTransition + " " + highestTarget
1649                            + " animating=" + highestTarget.mWinAnimator.isAnimationSet()
1650                            + " layer=" + highestTarget.mWinAnimator.mAnimLayer
1651                            + " new layer=" + target.mWinAnimator.mAnimLayer);
1652
1653                    if (appTransition.isTransitionSet()) {
1654                        // If we are currently setting up for an animation, hold everything until we
1655                        // can find out what will happen.
1656                        setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
1657                        return highestTarget;
1658                    } else if (highestTarget.mWinAnimator.isAnimationSet() &&
1659                            highestTarget.mWinAnimator.mAnimLayer > target.mWinAnimator.mAnimLayer) {
1660                        // If the window we are currently targeting is involved with an animation,
1661                        // and it is on top of the next target we will be over, then hold off on
1662                        // moving until that is done.
1663                        setInputMethodTarget(highestTarget, true, mInputMethodAnimLayerAdjustment);
1664                        return highestTarget;
1665                    }
1666                }
1667            }
1668
1669            if (DEBUG_INPUT_METHOD) Slog.w(TAG_WM, "Moving IM target from " + curTarget + " to "
1670                    + target + (SHOW_STACK_CRAWLS ? " Callers=" + Debug.getCallers(4) : ""));
1671            setInputMethodTarget(target, false, target.mAppToken != null
1672                    ? target.mAppToken.mAppAnimator.animLayerAdjustment : 0);
1673        }
1674
1675        return target;
1676    }
1677
1678    private void setInputMethodTarget(WindowState target, boolean targetWaitingAnim, int layerAdj) {
1679        if (target == mService.mInputMethodTarget
1680                && mService.mInputMethodTargetWaitingAnim == targetWaitingAnim
1681                && mInputMethodAnimLayerAdjustment == layerAdj) {
1682            return;
1683        }
1684
1685        mService.mInputMethodTarget = target;
1686        mService.mInputMethodTargetWaitingAnim = targetWaitingAnim;
1687        setInputMethodAnimLayerAdjustment(layerAdj);
1688        assignWindowLayers(false /* setLayoutNeeded */);
1689    }
1690
1691    boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
1692        if (top.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
1693            return top.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
1694        }
1695
1696        // Used to indicate we have reached the first window in the range we are interested in.
1697        mTmpWindow = null;
1698
1699        // TODO: Figure-out a more efficient way to do this.
1700        final WindowState candidate = getWindow(w -> {
1701            if (w == top) {
1702                // Reached the first window in the range we are interested in.
1703                mTmpWindow = w;
1704            }
1705            if (mTmpWindow == null) {
1706                return false;
1707            }
1708
1709            if (w.mAttrs.needsMenuKey != NEEDS_MENU_UNSET) {
1710                return true;
1711            }
1712            // If we reached the bottom of the range of windows we are considering,
1713            // assume no menu is needed.
1714            if (w == bottom) {
1715                return true;
1716            }
1717            return false;
1718        });
1719
1720        return candidate != null && candidate.mAttrs.needsMenuKey == NEEDS_MENU_SET_TRUE;
1721    }
1722
1723    void setLayoutNeeded() {
1724        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
1725        mLayoutNeeded = true;
1726    }
1727
1728    private void clearLayoutNeeded() {
1729        if (DEBUG_LAYOUT) Slog.w(TAG_WM, "clearLayoutNeeded: callers=" + Debug.getCallers(3));
1730        mLayoutNeeded = false;
1731    }
1732
1733    boolean isLayoutNeeded() {
1734        return mLayoutNeeded;
1735    }
1736
1737    void dumpTokens(PrintWriter pw, boolean dumpAll) {
1738        if (mTokenMap.isEmpty()) {
1739            return;
1740        }
1741        pw.println("  Display #" + mDisplayId);
1742        final Iterator<WindowToken> it = mTokenMap.values().iterator();
1743        while (it.hasNext()) {
1744            final WindowToken token = it.next();
1745            pw.print("  ");
1746            pw.print(token);
1747            if (dumpAll) {
1748                pw.println(':');
1749                token.dump(pw, "    ");
1750            } else {
1751                pw.println();
1752            }
1753        }
1754    }
1755
1756    void dumpWindowAnimators(PrintWriter pw, String subPrefix) {
1757        final int[] index = new int[1];
1758        forAllWindows(w -> {
1759            final WindowStateAnimator wAnim = w.mWinAnimator;
1760            pw.println(subPrefix + "Window #" + index[0] + ": " + wAnim);
1761            index[0] = index[0] + 1;
1762        }, false /* traverseTopToBottom */);
1763    }
1764
1765    void enableSurfaceTrace(FileDescriptor fd) {
1766        forAllWindows(w -> {
1767            w.mWinAnimator.enableSurfaceTrace(fd);
1768        }, true /* traverseTopToBottom */);
1769    }
1770
1771    void disableSurfaceTrace() {
1772        forAllWindows(w -> {
1773            w.mWinAnimator.disableSurfaceTrace();
1774        }, true /* traverseTopToBottom */);
1775    }
1776
1777    /**
1778     * Starts the Keyguard exit animation on all windows that don't belong to an app token.
1779     */
1780    void startKeyguardExitOnNonAppWindows(boolean onWallpaper, boolean goingToShade) {
1781        final WindowManagerPolicy policy = mService.mPolicy;
1782        forAllWindows(w -> {
1783            if (w.mAppToken == null && policy.canBeHiddenByKeyguardLw(w)) {
1784                w.mWinAnimator.setAnimation(
1785                        policy.createHiddenByKeyguardExit(onWallpaper, goingToShade));
1786            }
1787        }, true /* traverseTopToBottom */);
1788    }
1789
1790    boolean checkWaitingForWindows() {
1791
1792        mHaveBootMsg = false;
1793        mHaveApp = false;
1794        mHaveWallpaper = false;
1795        mHaveKeyguard = true;
1796
1797        final WindowState visibleWindow = getWindow(w -> {
1798            if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
1799                return true;
1800            }
1801            if (w.isDrawnLw()) {
1802                if (w.mAttrs.type == TYPE_BOOT_PROGRESS) {
1803                    mHaveBootMsg = true;
1804                } else if (w.mAttrs.type == TYPE_APPLICATION
1805                        || w.mAttrs.type == TYPE_DRAWN_APPLICATION) {
1806                    mHaveApp = true;
1807                } else if (w.mAttrs.type == TYPE_WALLPAPER) {
1808                    mHaveWallpaper = true;
1809                } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
1810                    mHaveKeyguard = mService.mPolicy.isKeyguardDrawnLw();
1811                }
1812            }
1813            return false;
1814        });
1815
1816        if (visibleWindow != null) {
1817            // We have a visible window.
1818            return true;
1819        }
1820
1821        // if the wallpaper service is disabled on the device, we're never going to have
1822        // wallpaper, don't bother waiting for it
1823        boolean wallpaperEnabled = mService.mContext.getResources().getBoolean(
1824                com.android.internal.R.bool.config_enableWallpaperService)
1825                && !mService.mOnlyCore;
1826
1827        if (DEBUG_SCREEN_ON || DEBUG_BOOT) Slog.i(TAG_WM,
1828                "******** booted=" + mService.mSystemBooted
1829                + " msg=" + mService.mShowingBootMessages
1830                + " haveBoot=" + mHaveBootMsg + " haveApp=" + mHaveApp
1831                + " haveWall=" + mHaveWallpaper + " wallEnabled=" + wallpaperEnabled
1832                + " haveKeyguard=" + mHaveKeyguard);
1833
1834        // If we are turning on the screen to show the boot message, don't do it until the boot
1835        // message is actually displayed.
1836        if (!mService.mSystemBooted && !mHaveBootMsg) {
1837            return true;
1838        }
1839
1840        // If we are turning on the screen after the boot is completed normally, don't do so until
1841        // we have the application and wallpaper.
1842        if (mService.mSystemBooted
1843                && ((!mHaveApp && !mHaveKeyguard) || (wallpaperEnabled && !mHaveWallpaper))) {
1844            return true;
1845        }
1846
1847        return false;
1848    }
1849
1850    void updateWindowsForAnimator(WindowAnimator animator) {
1851        mTmpWindowAnimator = animator;
1852        forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
1853    }
1854
1855    void updateWallpaperForAnimator(WindowAnimator animator) {
1856        resetAnimationBackgroundAnimator();
1857
1858        // Used to indicate a detached wallpaper.
1859        mTmpWindow = null;
1860        mTmpWindowAnimator = animator;
1861
1862        forAllWindows(mUpdateWallpaperForAnimator, true /* traverseTopToBottom */);
1863
1864        if (animator.mWindowDetachedWallpaper != mTmpWindow) {
1865            if (DEBUG_WALLPAPER) Slog.v(TAG, "Detached wallpaper changed from "
1866                    + animator.mWindowDetachedWallpaper + " to " + mTmpWindow);
1867            animator.mWindowDetachedWallpaper = mTmpWindow;
1868            animator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
1869        }
1870    }
1871
1872    void prepareWindowSurfaces() {
1873        forAllWindows(mPrepareWindowSurfaces, false /* traverseTopToBottom */);
1874    }
1875
1876    boolean inputMethodClientHasFocus(IInputMethodClient client) {
1877        final WindowState imFocus = computeImeTarget(false /* updateImeTarget */);
1878        if (imFocus == null) {
1879            return false;
1880        }
1881
1882        if (DEBUG_INPUT_METHOD) {
1883            Slog.i(TAG_WM, "Desired input method target: " + imFocus);
1884            Slog.i(TAG_WM, "Current focus: " + mService.mCurrentFocus);
1885            Slog.i(TAG_WM, "Last focus: " + mService.mLastFocus);
1886        }
1887
1888        final IInputMethodClient imeClient = imFocus.mSession.mClient;
1889
1890        if (DEBUG_INPUT_METHOD) {
1891            Slog.i(TAG_WM, "IM target client: " + imeClient);
1892            if (imeClient != null) {
1893                Slog.i(TAG_WM, "IM target client binder: " + imeClient.asBinder());
1894                Slog.i(TAG_WM, "Requesting client binder: " + client.asBinder());
1895            }
1896        }
1897
1898        return imeClient != null && imeClient.asBinder() == client.asBinder();
1899    }
1900
1901    boolean hasSecureWindowOnScreen() {
1902        final WindowState win = getWindow(
1903                w -> w.isOnScreen() && (w.mAttrs.flags & FLAG_SECURE) != 0);
1904        return win != null;
1905    }
1906
1907    void updateSystemUiVisibility(int visibility, int globalDiff) {
1908        forAllWindows(w -> {
1909            try {
1910                final int curValue = w.mSystemUiVisibility;
1911                final int diff = (curValue ^ visibility) & globalDiff;
1912                final int newValue = (curValue & ~diff) | (visibility & diff);
1913                if (newValue != curValue) {
1914                    w.mSeq++;
1915                    w.mSystemUiVisibility = newValue;
1916                }
1917                if (newValue != curValue || w.mAttrs.hasSystemUiListeners) {
1918                    w.mClient.dispatchSystemUiVisibilityChanged(w.mSeq,
1919                            visibility, newValue, diff);
1920                }
1921            } catch (RemoteException e) {
1922                // so sorry
1923            }
1924        }, true /* traverseTopToBottom */);
1925    }
1926
1927    void onWindowFreezeTimeout() {
1928        Slog.w(TAG_WM, "Window freeze timeout expired.");
1929        mService.mWindowsFreezingScreen = WINDOWS_FREEZING_SCREENS_TIMEOUT;
1930
1931        forAllWindows(w -> {
1932            if (!w.mOrientationChanging) {
1933                return;
1934            }
1935            w.mOrientationChanging = false;
1936            w.mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
1937                    - mService.mDisplayFreezeTime);
1938            Slog.w(TAG_WM, "Force clearing orientation change: " + w);
1939        }, true /* traverseTopToBottom */);
1940        mService.mWindowPlacerLocked.performSurfacePlacement();
1941    }
1942
1943    void waitForAllWindowsDrawn() {
1944        final WindowManagerPolicy policy = mService.mPolicy;
1945        forAllWindows(w -> {
1946            final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs);
1947            if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) {
1948                w.mWinAnimator.mDrawState = DRAW_PENDING;
1949                // Force add to mResizingWindows.
1950                w.mLastContentInsets.set(-1, -1, -1, -1);
1951                mService.mWaitingForDrawn.add(w);
1952            }
1953        }, true /* traverseTopToBottom */);
1954    }
1955
1956    // TODO: Super crazy long method that should be broken down...
1957    boolean applySurfaceChangesTransaction(boolean recoveringMemory) {
1958
1959        final int dw = mDisplayInfo.logicalWidth;
1960        final int dh = mDisplayInfo.logicalHeight;
1961        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
1962
1963        mTmpUpdateAllDrawn.clear();
1964
1965        int repeats = 0;
1966        do {
1967            repeats++;
1968            if (repeats > 6) {
1969                Slog.w(TAG, "Animation repeat aborted after too many iterations");
1970                clearLayoutNeeded();
1971                break;
1972            }
1973
1974            if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats("On entry to LockedInner",
1975                    pendingLayoutChanges);
1976
1977            // TODO(multi-display): For now adjusting wallpaper only on primary display to avoid
1978            // the wallpaper window jumping across displays.
1979            // Remove check for default display when there will be support for multiple wallpaper
1980            // targets (on different displays).
1981            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_WALLPAPER) != 0) {
1982                mWallpaperController.adjustWallpaperWindows(this);
1983            }
1984
1985            if (isDefaultDisplay && (pendingLayoutChanges & FINISH_LAYOUT_REDO_CONFIG) != 0) {
1986                if (DEBUG_LAYOUT) Slog.v(TAG, "Computing new config from layout");
1987                if (mService.updateOrientationFromAppTokensLocked(true, mDisplayId)) {
1988                    setLayoutNeeded();
1989                    mService.mH.obtainMessage(SEND_NEW_CONFIGURATION, mDisplayId).sendToTarget();
1990                }
1991            }
1992
1993            if ((pendingLayoutChanges & FINISH_LAYOUT_REDO_LAYOUT) != 0) {
1994                setLayoutNeeded();
1995            }
1996
1997            // FIRST LOOP: Perform a layout, if needed.
1998            if (repeats < LAYOUT_REPEAT_THRESHOLD) {
1999                performLayout(repeats == 1, false /* updateInputWindows */);
2000            } else {
2001                Slog.w(TAG, "Layout repeat skipped after too many iterations");
2002            }
2003
2004            // FIRST AND ONE HALF LOOP: Make WindowManagerPolicy think it is animating.
2005            pendingLayoutChanges = 0;
2006
2007            if (isDefaultDisplay) {
2008                mService.mPolicy.beginPostLayoutPolicyLw(dw, dh);
2009                forAllWindows(mApplyPostLayoutPolicy, true /* traverseTopToBottom */);
2010                pendingLayoutChanges |= mService.mPolicy.finishPostLayoutPolicyLw();
2011                if (DEBUG_LAYOUT_REPEATS) surfacePlacer.debugLayoutRepeats(
2012                        "after finishPostLayoutPolicyLw", pendingLayoutChanges);
2013            }
2014        } while (pendingLayoutChanges != 0);
2015
2016        mTmpApplySurfaceChangesTransactionState.reset();
2017        resetDimming();
2018
2019        mTmpRecoveringMemory = recoveringMemory;
2020        forAllWindows(mApplySurfaceChangesTransaction, true /* traverseTopToBottom */);
2021
2022        mService.mDisplayManagerInternal.setDisplayProperties(mDisplayId,
2023                mTmpApplySurfaceChangesTransactionState.displayHasContent,
2024                mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
2025                mTmpApplySurfaceChangesTransactionState.preferredModeId,
2026                true /* inTraversal, must call performTraversalInTrans... below */);
2027
2028        stopDimmingIfNeeded();
2029
2030        while (!mTmpUpdateAllDrawn.isEmpty()) {
2031            final AppWindowToken atoken = mTmpUpdateAllDrawn.removeLast();
2032            // See if any windows have been drawn, so they (and others associated with them)
2033            // can now be shown.
2034            atoken.updateAllDrawn(this);
2035        }
2036
2037        return mTmpApplySurfaceChangesTransactionState.focusDisplayed;
2038    }
2039
2040    void performLayout(boolean initial, boolean updateInputWindows) {
2041        if (!isLayoutNeeded()) {
2042            return;
2043        }
2044        clearLayoutNeeded();
2045
2046        final int dw = mDisplayInfo.logicalWidth;
2047        final int dh = mDisplayInfo.logicalHeight;
2048
2049        if (DEBUG_LAYOUT) {
2050            Slog.v(TAG, "-------------------------------------");
2051            Slog.v(TAG, "performLayout: needed=" + isLayoutNeeded() + " dw=" + dw + " dh=" + dh);
2052        }
2053
2054        mService.mPolicy.beginLayoutLw(isDefaultDisplay, dw, dh, mService.mRotation,
2055                getConfiguration().uiMode);
2056        if (isDefaultDisplay) {
2057            // Not needed on non-default displays.
2058            mService.mSystemDecorLayer = mService.mPolicy.getSystemDecorLayerLw();
2059            mService.mScreenRect.set(0, 0, dw, dh);
2060        }
2061
2062        mService.mPolicy.getContentRectLw(mContentRect);
2063
2064        int seq = mService.mLayoutSeq + 1;
2065        if (seq < 0) seq = 0;
2066        mService.mLayoutSeq = seq;
2067
2068        // Used to indicate that we have processed the dream window and all additional windows are
2069        // behind it.
2070        mTmpWindow = null;
2071        mTmpInitial = initial;
2072
2073        // First perform layout of any root windows (not attached to another window).
2074        forAllWindows(mPerformLayout, true /* traverseTopToBottom */);
2075
2076        // Used to indicate that we have processed the dream window and all additional attached
2077        // windows are behind it.
2078        mTmpWindow2 = mTmpWindow;
2079        mTmpWindow = null;
2080
2081        // Now perform layout of attached windows, which usually depend on the position of the
2082        // window they are attached to. XXX does not deal with windows that are attached to windows
2083        // that are themselves attached.
2084        forAllWindows(mPerformLayoutAttached, true /* traverseTopToBottom */);
2085
2086        // Window frames may have changed. Tell the input dispatcher about it.
2087        mService.mInputMonitor.layoutInputConsumers(dw, dh);
2088        mService.mInputMonitor.setUpdateInputWindowsNeededLw();
2089        if (updateInputWindows) {
2090            mService.mInputMonitor.updateInputWindowsLw(false /*force*/);
2091        }
2092
2093        mService.mPolicy.finishLayoutLw();
2094        mService.mH.sendEmptyMessage(UPDATE_DOCKED_STACK_DIVIDER);
2095    }
2096
2097    /**
2098     * Takes a snapshot of the display.  In landscape mode this grabs the whole screen.
2099     * In portrait mode, it grabs the full screenshot.
2100     *
2101     * @param width the width of the target bitmap
2102     * @param height the height of the target bitmap
2103     * @param includeFullDisplay true if the screen should not be cropped before capture
2104     * @param frameScale the scale to apply to the frame, only used when width = -1 and height = -1
2105     * @param config of the output bitmap
2106     * @param wallpaperOnly true if only the wallpaper layer should be included in the screenshot
2107     */
2108    Bitmap screenshotApplications(IBinder appToken, int width, int height,
2109            boolean includeFullDisplay, float frameScale, Bitmap.Config config,
2110            boolean wallpaperOnly) {
2111        int dw = mDisplayInfo.logicalWidth;
2112        int dh = mDisplayInfo.logicalHeight;
2113        if (dw == 0 || dh == 0) {
2114            if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2115                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
2116            return null;
2117        }
2118
2119        Bitmap bm = null;
2120
2121        mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
2122        final Rect frame = new Rect();
2123        final Rect stackBounds = new Rect();
2124
2125        boolean includeImeInScreenshot;
2126        synchronized(mService.mWindowMap) {
2127            final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
2128                    ? mService.mInputMethodTarget.mAppToken : null;
2129            // We only include the Ime in the screenshot if the app we are screenshoting is the IME
2130            // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
2131            // mode because the frame of the IME might not overlap with that of the app.
2132            // E.g. IME target app at the top in split-screen mode and the IME at the bottom
2133            // overlapping with the bottom app.
2134            includeImeInScreenshot = imeTargetAppToken != null
2135                    && imeTargetAppToken.appToken != null
2136                    && imeTargetAppToken.appToken.asBinder() == appToken
2137                    && !mService.mInputMethodTarget.isInMultiWindowMode();
2138        }
2139
2140        final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
2141                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
2142
2143        synchronized(mService.mWindowMap) {
2144            // Figure out the part of the screen that is actually the app.
2145            mScreenshotApplicationState.appWin = null;
2146            forAllWindows(w -> {
2147                if (!w.mHasSurface) {
2148                    return false;
2149                }
2150                if (w.mLayer >= aboveAppLayer) {
2151                    return false;
2152                }
2153                if (wallpaperOnly && !w.mIsWallpaper) {
2154                    return false;
2155                }
2156                if (w.mIsImWindow) {
2157                    if (!includeImeInScreenshot) {
2158                        return false;
2159                    }
2160                } else if (w.mIsWallpaper) {
2161                    // If this is the wallpaper layer and we're only looking for the wallpaper layer
2162                    // then the target window state is this one.
2163                    if (wallpaperOnly) {
2164                        mScreenshotApplicationState.appWin = w;
2165                    }
2166
2167                    if (mScreenshotApplicationState.appWin == null) {
2168                        // We have not ran across the target window yet, so it is probably behind
2169                        // the wallpaper. This can happen when the keyguard is up and all windows
2170                        // are moved behind the wallpaper. We don't want to include the wallpaper
2171                        // layer in the screenshot as it will cover-up the layer of the target
2172                        // window.
2173                        return false;
2174                    }
2175                    // Fall through. The target window is in front of the wallpaper. For this
2176                    // case we want to include the wallpaper layer in the screenshot because
2177                    // the target window might have some transparent areas.
2178                } else if (appToken != null) {
2179                    if (w.mAppToken == null || w.mAppToken.token != appToken) {
2180                        // This app window is of no interest if it is not associated with the
2181                        // screenshot app.
2182                        return false;
2183                    }
2184                    mScreenshotApplicationState.appWin = w;
2185                }
2186
2187                // Include this window.
2188
2189                final WindowStateAnimator winAnim = w.mWinAnimator;
2190                int layer = winAnim.mSurfaceController.getLayer();
2191                if (mScreenshotApplicationState.maxLayer < layer) {
2192                    mScreenshotApplicationState.maxLayer = layer;
2193                }
2194                if (mScreenshotApplicationState.minLayer > layer) {
2195                    mScreenshotApplicationState.minLayer = layer;
2196                }
2197
2198                // Don't include wallpaper in bounds calculation
2199                if (!includeFullDisplay && !w.mIsWallpaper) {
2200                    final Rect wf = w.mFrame;
2201                    final Rect cr = w.mContentInsets;
2202                    int left = wf.left + cr.left;
2203                    int top = wf.top + cr.top;
2204                    int right = wf.right - cr.right;
2205                    int bottom = wf.bottom - cr.bottom;
2206                    frame.union(left, top, right, bottom);
2207                    w.getVisibleBounds(stackBounds);
2208                    if (!Rect.intersects(frame, stackBounds)) {
2209                        // Set frame empty if there's no intersection.
2210                        frame.setEmpty();
2211                    }
2212                }
2213
2214                final boolean foundTargetWs =
2215                        (w.mAppToken != null && w.mAppToken.token == appToken)
2216                                || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
2217                if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) {
2218                    mScreenshotApplicationState.screenshotReady = true;
2219                }
2220
2221                if (w.isObscuringDisplay()){
2222                    return true;
2223                }
2224                return false;
2225            }, true /* traverseTopToBottom */);
2226
2227            final WindowState appWin = mScreenshotApplicationState.appWin;
2228            final boolean screenshotReady = mScreenshotApplicationState.screenshotReady;
2229            final int maxLayer = mScreenshotApplicationState.maxLayer;
2230            final int minLayer = mScreenshotApplicationState.minLayer;
2231
2232            if (appToken != null && appWin == null) {
2233                // Can't find a window to snapshot.
2234                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
2235                        "Screenshot: Couldn't find a surface matching " + appToken);
2236                return null;
2237            }
2238
2239            if (!screenshotReady) {
2240                Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
2241                        " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
2242                        appWin.mWinAnimator.mDrawState)));
2243                return null;
2244            }
2245
2246            // Screenshot is ready to be taken. Everything from here below will continue
2247            // through the bottom of the loop and return a value. We only stay in the loop
2248            // because we don't want to release the mWindowMap lock until the screenshot is
2249            // taken.
2250
2251            if (maxLayer == 0) {
2252                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2253                        + ": returning null maxLayer=" + maxLayer);
2254                return null;
2255            }
2256
2257            if (!includeFullDisplay) {
2258                // Constrain frame to the screen size.
2259                if (!frame.intersect(0, 0, dw, dh)) {
2260                    frame.setEmpty();
2261                }
2262            } else {
2263                // Caller just wants entire display.
2264                frame.set(0, 0, dw, dh);
2265            }
2266            if (frame.isEmpty()) {
2267                return null;
2268            }
2269
2270            if (width < 0) {
2271                width = (int) (frame.width() * frameScale);
2272            }
2273            if (height < 0) {
2274                height = (int) (frame.height() * frameScale);
2275            }
2276
2277            // Tell surface flinger what part of the image to crop. Take the top
2278            // right part of the application, and crop the larger dimension to fit.
2279            Rect crop = new Rect(frame);
2280            if (width / (float) frame.width() < height / (float) frame.height()) {
2281                int cropWidth = (int)((float)width / (float)height * frame.height());
2282                crop.right = crop.left + cropWidth;
2283            } else {
2284                int cropHeight = (int)((float)height / (float)width * frame.width());
2285                crop.bottom = crop.top + cropHeight;
2286            }
2287
2288            // The screenshot API does not apply the current screen rotation.
2289            int rot = mDisplay.getRotation();
2290
2291            if (rot == ROTATION_90 || rot == ROTATION_270) {
2292                rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
2293            }
2294
2295            // Surfaceflinger is not aware of orientation, so convert our logical
2296            // crop to surfaceflinger's portrait orientation.
2297            convertCropForSurfaceFlinger(crop, rot, dw, dh);
2298
2299            if (DEBUG_SCREENSHOT) {
2300                Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
2301                        + maxLayer + " appToken=" + appToken);
2302                forAllWindows(w -> {
2303                    final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController;
2304                    Slog.i(TAG_WM, w + ": " + w.mLayer
2305                            + " animLayer=" + w.mWinAnimator.mAnimLayer
2306                            + " surfaceLayer=" + ((controller == null)
2307                            ? "null" : controller.getLayer()));
2308                }, false /* traverseTopToBottom */);
2309            }
2310
2311            final ScreenRotationAnimation screenRotationAnimation =
2312                    mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
2313            final boolean inRotation = screenRotationAnimation != null &&
2314                    screenRotationAnimation.isAnimating();
2315            if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
2316                    "Taking screenshot while rotating");
2317
2318            // We force pending transactions to flush before taking
2319            // the screenshot by pushing an empty synchronous transaction.
2320            SurfaceControl.openTransaction();
2321            SurfaceControl.closeTransactionSync();
2322
2323            bm = SurfaceControl.screenshot(crop, width, height, minLayer, maxLayer,
2324                    inRotation, rot);
2325            if (bm == null) {
2326                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
2327                        + ") to layer " + maxLayer);
2328                return null;
2329            }
2330        }
2331
2332        if (DEBUG_SCREENSHOT) {
2333            // TEST IF IT's ALL BLACK
2334            int[] buffer = new int[bm.getWidth() * bm.getHeight()];
2335            bm.getPixels(buffer, 0, bm.getWidth(), 0, 0, bm.getWidth(), bm.getHeight());
2336            boolean allBlack = true;
2337            final int firstColor = buffer[0];
2338            for (int i = 0; i < buffer.length; i++) {
2339                if (buffer[i] != firstColor) {
2340                    allBlack = false;
2341                    break;
2342                }
2343            }
2344            if (allBlack) {
2345                final WindowState appWin = mScreenshotApplicationState.appWin;
2346                final int maxLayer = mScreenshotApplicationState.maxLayer;
2347                final int minLayer = mScreenshotApplicationState.minLayer;
2348                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
2349                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
2350                        (appWin != null ?
2351                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
2352                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
2353            }
2354        }
2355
2356        // Create a copy of the screenshot that is immutable and backed in ashmem.
2357        // This greatly reduces the overhead of passing the bitmap between processes.
2358        Bitmap ret = bm.createAshmemBitmap(config);
2359        bm.recycle();
2360        return ret;
2361    }
2362
2363    // TODO: Can this use createRotationMatrix()?
2364    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
2365        if (rot == Surface.ROTATION_90) {
2366            final int tmp = crop.top;
2367            crop.top = dw - crop.right;
2368            crop.right = crop.bottom;
2369            crop.bottom = dw - crop.left;
2370            crop.left = tmp;
2371        } else if (rot == Surface.ROTATION_180) {
2372            int tmp = crop.top;
2373            crop.top = dh - crop.bottom;
2374            crop.bottom = dh - tmp;
2375            tmp = crop.right;
2376            crop.right = dw - crop.left;
2377            crop.left = dw - tmp;
2378        } else if (rot == Surface.ROTATION_270) {
2379            final int tmp = crop.top;
2380            crop.top = crop.left;
2381            crop.left = dh - crop.bottom;
2382            crop.bottom = crop.right;
2383            crop.right = dh - tmp;
2384        }
2385    }
2386
2387    void onSeamlessRotationTimeout() {
2388        // Used to indicate the layout is needed.
2389        mTmpWindow = null;
2390
2391        forAllWindows(w -> {
2392            if (!w.mSeamlesslyRotated) {
2393                return;
2394            }
2395            mTmpWindow = w;
2396            w.setDisplayLayoutNeeded();
2397            mService.markForSeamlessRotation(w, false);
2398        }, true /* traverseTopToBottom */);
2399
2400        if (mTmpWindow != null) {
2401            mService.mWindowPlacerLocked.performSurfacePlacement();
2402        }
2403    }
2404
2405    static final class TaskForResizePointSearchResult {
2406        boolean searchDone;
2407        Task taskForResize;
2408
2409        void reset() {
2410            searchDone = false;
2411            taskForResize = null;
2412        }
2413    }
2414
2415    private static final class ApplySurfaceChangesTransactionState {
2416        boolean displayHasContent;
2417        boolean obscured;
2418        boolean syswin;
2419        boolean focusDisplayed;
2420        float preferredRefreshRate;
2421        int preferredModeId;
2422
2423        void reset() {
2424            displayHasContent = false;
2425            obscured = false;
2426            syswin = false;
2427            focusDisplayed = false;
2428            preferredRefreshRate = 0;
2429            preferredModeId = 0;
2430        }
2431    }
2432
2433    private static final class ScreenshotApplicationState {
2434        WindowState appWin;
2435        int maxLayer;
2436        int minLayer;
2437        boolean screenshotReady;
2438
2439        void reset(boolean screenshotReady) {
2440            appWin = null;
2441            maxLayer = 0;
2442            minLayer = 0;
2443            this.screenshotReady = screenshotReady;
2444            minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
2445        }
2446    }
2447
2448    /**
2449     * Base class for any direct child window container of {@link #DisplayContent} need to inherit
2450     * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
2451     * homogeneous children type which is currently required by sub-classes of
2452     * {@link WindowContainer} class.
2453     */
2454    static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
2455
2456        int size() {
2457            return mChildren.size();
2458        }
2459
2460        E get(int index) {
2461            return mChildren.get(index);
2462        }
2463
2464        @Override
2465        boolean fillsParent() {
2466            return true;
2467        }
2468
2469        @Override
2470        boolean isVisible() {
2471            return true;
2472        }
2473    }
2474
2475    /**
2476     * Window container class that contains all containers on this display relating to Apps.
2477     * I.e Activities.
2478     */
2479    private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
2480
2481        /**
2482         * Adds the stack to this container.
2483         * @see WindowManagerService#addStackToDisplay(int, int, boolean)
2484         */
2485        void addStackToDisplay(TaskStack stack, boolean onTop) {
2486            if (stack.mStackId == HOME_STACK_ID) {
2487                if (mHomeStack != null) {
2488                    throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
2489                }
2490                mHomeStack = stack;
2491            }
2492            addChild(stack, onTop);
2493            stack.onDisplayChanged(DisplayContent.this);
2494        }
2495
2496        /** Removes the stack from its container and prepare for changing the parent. */
2497        void removeStackFromDisplay(TaskStack stack) {
2498            removeChild(stack);
2499            stack.onRemovedFromDisplay();
2500        }
2501
2502        void moveStack(TaskStack stack, boolean toTop) {
2503            if (StackId.isAlwaysOnTop(stack.mStackId) && !toTop) {
2504                // This stack is always-on-top silly...
2505                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + stack + " to bottom");
2506                return;
2507            }
2508
2509            if (!mChildren.contains(stack)) {
2510                Slog.wtf(TAG_WM, "moving stack that was not added: " + stack, new Throwable());
2511            }
2512            removeChild(stack);
2513            addChild(stack, toTop);
2514        }
2515
2516        private void addChild(TaskStack stack, boolean toTop) {
2517            int addIndex = toTop ? mChildren.size() : 0;
2518
2519            if (toTop
2520                    && mService.isStackVisibleLocked(PINNED_STACK_ID)
2521                    && stack.mStackId != PINNED_STACK_ID) {
2522                // The pinned stack is always the top most stack (always-on-top) when it is visible.
2523                // So, stack is moved just below the pinned stack.
2524                addIndex--;
2525                TaskStack topStack = mChildren.get(addIndex);
2526                if (topStack.mStackId != PINNED_STACK_ID) {
2527                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
2528                }
2529            }
2530            addChild(stack, addIndex);
2531            setLayoutNeeded();
2532        }
2533
2534        @Override
2535        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
2536                boolean traverseTopToBottom) {
2537            if (traverseTopToBottom) {
2538                if (super.forAllWindows(callback, traverseTopToBottom)) {
2539                    return true;
2540                }
2541                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
2542                    return true;
2543                }
2544            } else {
2545                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
2546                    return true;
2547                }
2548                if (super.forAllWindows(callback, traverseTopToBottom)) {
2549                    return true;
2550                }
2551            }
2552            return false;
2553        }
2554
2555        private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
2556                boolean traverseTopToBottom) {
2557            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
2558            // app tokens.
2559            // TODO: Investigate if we need to continue to do this or if we can just process them
2560            // in-order.
2561            if (traverseTopToBottom) {
2562                for (int i = mChildren.size() - 1; i >= 0; --i) {
2563                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
2564                    for (int j = appTokens.size() - 1; j >= 0; --j) {
2565                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
2566                                traverseTopToBottom)) {
2567                            return true;
2568                        }
2569                    }
2570                }
2571            } else {
2572                final int count = mChildren.size();
2573                for (int i = 0; i < count; ++i) {
2574                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
2575                    final int appTokensCount = appTokens.size();
2576                    for (int j = 0; j < appTokensCount; j++) {
2577                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
2578                                traverseTopToBottom)) {
2579                            return true;
2580                        }
2581                    }
2582                }
2583            }
2584            return false;
2585        }
2586
2587        @Override
2588        int getOrientation() {
2589            if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
2590                    || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
2591                // Apps and their containers are not allowed to specify an orientation while the
2592                // docked or freeform stack is visible...except for the home stack/task if the
2593                // docked stack is minimized and it actually set something.
2594                if (mHomeStack != null && mHomeStack.isVisible()
2595                        && mDividerControllerLocked.isMinimizedDock()) {
2596                    final int orientation = mHomeStack.getOrientation();
2597                    if (orientation != SCREEN_ORIENTATION_UNSET) {
2598                        return orientation;
2599                    }
2600                }
2601                return SCREEN_ORIENTATION_UNSPECIFIED;
2602            }
2603
2604            final int orientation = super.getOrientation();
2605            if (orientation != SCREEN_ORIENTATION_UNSET
2606                    && orientation != SCREEN_ORIENTATION_BEHIND) {
2607                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
2608                        "App is requesting an orientation, return " + orientation);
2609                return orientation;
2610            }
2611
2612            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
2613                    "No app is requesting an orientation, return " + mService.mLastOrientation);
2614            // The next app has not been requested to be visible, so we keep the current orientation
2615            // to prevent freezing/unfreezing the display too early.
2616            return mService.mLastOrientation;
2617        }
2618    }
2619
2620    /**
2621     * Window container class that contains all containers on this display that are not related to
2622     * Apps. E.g. status bar.
2623     */
2624    private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
2625        final LinkedList<WindowState> mTmpWindows = new LinkedList();
2626
2627        private final ToBooleanFunction<WindowState> mCollectWindowsInOrder = w -> {
2628            int addIndex = mTmpWindows.size();
2629            for (int i = mTmpWindows.size() - 1; i >= 0; --i) {
2630                final WindowState current = mTmpWindows.get(i);
2631                if (w.mBaseLayer > current.mBaseLayer) {
2632                    break;
2633                }
2634                addIndex = i;
2635            }
2636
2637            mTmpWindows.add(addIndex, w);
2638            return false;
2639        };
2640
2641        /**
2642         * Compares two child window tokens returns -1 if the first is lesser than the second in
2643         * terms of z-order and 1 otherwise.
2644         */
2645        private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
2646                // Tokens with higher base layer are z-ordered on-top.
2647                mService.mPolicy.windowTypeToLayerLw(token1.windowType)
2648                < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
2649
2650        private final Predicate<WindowState> mGetOrientingWindow = w -> {
2651            if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
2652                return false;
2653            }
2654            final int req = w.mAttrs.screenOrientation;
2655            if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
2656                    || req == SCREEN_ORIENTATION_UNSET) {
2657                return false;
2658            }
2659            return true;
2660        };
2661
2662        private final String mName;
2663        NonAppWindowContainers(String name) {
2664            mName = name;
2665        }
2666
2667        void addChild(WindowToken token) {
2668            addChild(token, mWindowComparator);
2669        }
2670
2671        @Override
2672        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
2673                boolean traverseTopToBottom) {
2674            // Hack to work around WindowToken containing windows of various types there by causing
2675            // the windows not to be returned in visual order if there is another token with a
2676            // window that should be z-order in-between the windows of the first token. This is an
2677            // issue due to the various window types sys-ui adds with its token.
2678            // TODO: Have a separate token for each type of window sys-ui wants to add. Would
2679            // require some changes to sys-ui on the token it uses for window creation vs. just
2680            // using the default token of its process.
2681            mTmpWindows.clear();
2682            super.forAllWindows(mCollectWindowsInOrder, false /* traverseTopToBottom */);
2683
2684            while(!mTmpWindows.isEmpty()) {
2685                final WindowState current = traverseTopToBottom
2686                        ? mTmpWindows.pollLast() : mTmpWindows.pollFirst();
2687                if (callback.apply(current)) {
2688                    return true;
2689                }
2690            }
2691            return false;
2692        }
2693
2694        @Override
2695        int getOrientation() {
2696            final WindowManagerPolicy policy = mService.mPolicy;
2697            // Find a window requesting orientation.
2698            final WindowState win = getWindow(mGetOrientingWindow);
2699
2700            if (win != null) {
2701                final int req = win.mAttrs.screenOrientation;
2702                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
2703                if (policy.isKeyguardHostWindow(win.mAttrs)) {
2704                    mService.mLastKeyguardForcedOrientation = req;
2705                }
2706                return (mService.mLastWindowForcedOrientation = req);
2707            }
2708
2709            mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
2710
2711            if (policy.isKeyguardShowingAndNotOccluded()) {
2712                return mService.mLastKeyguardForcedOrientation;
2713            }
2714
2715            return SCREEN_ORIENTATION_UNSET;
2716        }
2717
2718        @Override
2719        String getName() {
2720            return mName;
2721        }
2722    }
2723}
2724