DisplayContent.java revision 6a7a85991d38e1e0fc6d33edede5be64e67560c7
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.GraphicBuffer;
98import android.graphics.Matrix;
99import android.graphics.Rect;
100import android.graphics.RectF;
101import android.graphics.Region;
102import android.graphics.Region.Op;
103import android.hardware.display.DisplayManagerInternal;
104import android.os.Debug;
105import android.os.Handler;
106import android.os.IBinder;
107import android.os.RemoteException;
108import android.os.SystemClock;
109import android.util.DisplayMetrics;
110import android.util.MutableBoolean;
111import android.util.Slog;
112import android.view.Display;
113import android.view.DisplayInfo;
114import android.view.Surface;
115import android.view.SurfaceControl;
116import android.view.WindowManagerPolicy;
117
118import com.android.internal.util.ToBooleanFunction;
119import com.android.internal.view.IInputMethodClient;
120
121import java.io.FileDescriptor;
122import java.io.PrintWriter;
123import java.util.ArrayList;
124import java.util.Comparator;
125import java.util.HashMap;
126import java.util.Iterator;
127import java.util.LinkedList;
128import java.util.List;
129import java.util.function.Consumer;
130import java.util.function.Predicate;
131
132/**
133 * Utility class for keeping track of the WindowStates and other pertinent contents of a
134 * particular Display.
135 *
136 * IMPORTANT: No method from this class should ever be used without holding
137 * WindowManagerService.mWindowMap.
138 */
139class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer> {
140    private static final String TAG = TAG_WITH_CLASS_NAME ? "DisplayContent" : TAG_WM;
141
142    /** Unique identifier of this stack. */
143    private final int mDisplayId;
144
145    /** The containers below are the only child containers the display can have. */
146    // Contains all window containers that are related to apps (Activities)
147    private final TaskStackContainers mTaskStackContainers = new TaskStackContainers();
148    // Contains all non-app window containers that should be displayed above the app containers
149    // (e.g. Status bar)
150    private final NonAppWindowContainers mAboveAppWindowsContainers =
151            new NonAppWindowContainers("mAboveAppWindowsContainers");
152    // Contains all non-app window containers that should be displayed below the app containers
153    // (e.g. Wallpaper).
154    private final NonAppWindowContainers mBelowAppWindowsContainers =
155            new NonAppWindowContainers("mBelowAppWindowsContainers");
156    // Contains all IME window containers. Note that the z-ordering of the IME windows will depend
157    // on the IME target. We mainly have this container grouping so we can keep track of all the IME
158    // window containers together and move them in-sync if/when needed.
159    private final NonAppWindowContainers mImeWindowsContainers =
160            new NonAppWindowContainers("mImeWindowsContainers");
161
162    private WindowState mTmpWindow;
163    private WindowState mTmpWindow2;
164    private WindowAnimator mTmpWindowAnimator;
165    private boolean mTmpRecoveringMemory;
166    private boolean mUpdateImeTarget;
167    private boolean mTmpInitial;
168
169    // Mapping from a token IBinder to a WindowToken object on this display.
170    private final HashMap<IBinder, WindowToken> mTokenMap = new HashMap();
171
172    int mInitialDisplayWidth = 0;
173    int mInitialDisplayHeight = 0;
174    int mInitialDisplayDensity = 0;
175    int mBaseDisplayWidth = 0;
176    int mBaseDisplayHeight = 0;
177    int mBaseDisplayDensity = 0;
178    boolean mDisplayScalingDisabled;
179    private final DisplayInfo mDisplayInfo = new DisplayInfo();
180    private final Display mDisplay;
181    private final DisplayMetrics mDisplayMetrics = new DisplayMetrics();
182
183    Rect mBaseDisplayRect = new Rect();
184    private Rect mContentRect = new Rect();
185
186    // Accessed directly by all users.
187    private boolean mLayoutNeeded;
188    int pendingLayoutChanges;
189    // TODO(multi-display): remove some of the usages.
190    boolean isDefaultDisplay;
191
192    /** Window tokens that are in the process of exiting, but still on screen for animations. */
193    final ArrayList<WindowToken> mExitingTokens = new ArrayList<>();
194
195    /** A special TaskStack with id==HOME_STACK_ID that moves to the bottom whenever any TaskStack
196     * (except a future lockscreen TaskStack) moves to the top. */
197    private TaskStack mHomeStack = null;
198
199    /** Detect user tapping outside of current focused task bounds .*/
200    TaskTapPointerEventListener mTapDetector;
201
202    /** Detect user tapping outside of current focused stack bounds .*/
203    private Region mTouchExcludeRegion = new Region();
204
205    /** Save allocating when calculating rects */
206    private final Rect mTmpRect = new Rect();
207    private final Rect mTmpRect2 = new Rect();
208    private final RectF mTmpRectF = new RectF();
209    private final Matrix mTmpMatrix = new Matrix();
210    private final Region mTmpRegion = new Region();
211
212    WindowManagerService mService;
213
214    /** Remove this display when animation on it has completed. */
215    private boolean mDeferredRemoval;
216
217    final DockedStackDividerController mDividerControllerLocked;
218    final PinnedStackController mPinnedStackControllerLocked;
219
220    DimLayerController mDimLayerController;
221
222    final ArrayList<WindowState> mTapExcludedWindows = new ArrayList<>();
223
224    private boolean mHaveBootMsg = false;
225    private boolean mHaveApp = false;
226    private boolean mHaveWallpaper = false;
227    private boolean mHaveKeyguard = true;
228
229    private final LinkedList<AppWindowToken> mTmpUpdateAllDrawn = new LinkedList();
230
231    private final TaskForResizePointSearchResult mTmpTaskForResizePointSearchResult =
232            new TaskForResizePointSearchResult();
233    private final ApplySurfaceChangesTransactionState mTmpApplySurfaceChangesTransactionState =
234            new ApplySurfaceChangesTransactionState();
235    private final ScreenshotApplicationState mScreenshotApplicationState =
236            new ScreenshotApplicationState();
237
238    // True if this display is in the process of being removed. Used to determine if the removal of
239    // the display's direct children should be allowed.
240    private boolean mRemovingDisplay = false;
241
242    private final WindowLayersController mLayersController;
243    WallpaperController mWallpaperController;
244    int mInputMethodAnimLayerAdjustment;
245
246    private final Consumer<WindowState> mUpdateWindowsForAnimator = w -> {
247        WindowStateAnimator winAnimator = w.mWinAnimator;
248        if (winAnimator.hasSurface()) {
249            final boolean wasAnimating = winAnimator.mWasAnimating;
250            final boolean nowAnimating = winAnimator.stepAnimationLocked(
251                    mTmpWindowAnimator.mCurrentTime);
252            winAnimator.mWasAnimating = nowAnimating;
253            mTmpWindowAnimator.orAnimating(nowAnimating);
254
255            if (DEBUG_WALLPAPER) Slog.v(TAG,
256                    w + ": wasAnimating=" + wasAnimating + ", nowAnimating=" + nowAnimating);
257
258            if (wasAnimating && !winAnimator.mAnimating
259                    && mWallpaperController.isWallpaperTarget(w)) {
260                mTmpWindowAnimator.mBulkUpdateParams |= SET_WALLPAPER_MAY_CHANGE;
261                pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
262                if (DEBUG_LAYOUT_REPEATS) {
263                    mService.mWindowPlacerLocked.debugLayoutRepeats(
264                            "updateWindowsAndWallpaperLocked 2", pendingLayoutChanges);
265                }
266            }
267        }
268
269        final AppWindowToken atoken = w.mAppToken;
270        if (winAnimator.mDrawState == READY_TO_SHOW) {
271            if (atoken == null || atoken.allDrawn) {
272                if (w.performShowLocked()) {
273                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
274                    if (DEBUG_LAYOUT_REPEATS) {
275                        mService.mWindowPlacerLocked.debugLayoutRepeats(
276                                "updateWindowsAndWallpaperLocked 5", pendingLayoutChanges);
277                    }
278                }
279            }
280        }
281        final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
282        if (appAnimator != null && appAnimator.thumbnail != null) {
283            if (appAnimator.thumbnailTransactionSeq
284                    != mTmpWindowAnimator.mAnimTransactionSequence) {
285                appAnimator.thumbnailTransactionSeq =
286                        mTmpWindowAnimator.mAnimTransactionSequence;
287                appAnimator.thumbnailLayer = 0;
288            }
289            if (appAnimator.thumbnailLayer < winAnimator.mAnimLayer) {
290                appAnimator.thumbnailLayer = winAnimator.mAnimLayer;
291            }
292        }
293    };
294
295    private final Consumer<WindowState> mUpdateWallpaperForAnimator = w -> {
296        final WindowStateAnimator winAnimator = w.mWinAnimator;
297        if (winAnimator.mSurfaceController == null || !winAnimator.hasSurface()) {
298            return;
299        }
300
301        final int flags = w.mAttrs.flags;
302
303        // If this window is animating, make a note that we have an animating window and take
304        // care of a request to run a detached wallpaper animation.
305        if (winAnimator.mAnimating) {
306            if (winAnimator.mAnimation != null) {
307                if ((flags & FLAG_SHOW_WALLPAPER) != 0
308                        && winAnimator.mAnimation.getDetachWallpaper()) {
309                    mTmpWindow = w;
310                }
311                final int color = winAnimator.mAnimation.getBackgroundColor();
312                if (color != 0) {
313                    final TaskStack stack = w.getStack();
314                    if (stack != null) {
315                        stack.setAnimationBackground(winAnimator, color);
316                    }
317                }
318            }
319            mTmpWindowAnimator.setAnimating(true);
320        }
321
322        // If this window's app token is running a detached wallpaper animation, make a note so
323        // we can ensure the wallpaper is displayed behind it.
324        final AppWindowAnimator appAnimator = winAnimator.mAppAnimator;
325        if (appAnimator != null && appAnimator.animation != null
326                && appAnimator.animating) {
327            if ((flags & FLAG_SHOW_WALLPAPER) != 0
328                    && appAnimator.animation.getDetachWallpaper()) {
329                mTmpWindow = w;
330            }
331
332            final int color = appAnimator.animation.getBackgroundColor();
333            if (color != 0) {
334                final TaskStack stack = w.getStack();
335                if (stack != null) {
336                    stack.setAnimationBackground(winAnimator, color);
337                }
338            }
339        }
340    };
341
342    private final Consumer<WindowState> mSetInputMethodAnimLayerAdjustment =
343            w -> w.adjustAnimLayer(mInputMethodAnimLayerAdjustment);
344
345    private final Consumer<WindowState> mScheduleToastTimeout = w -> {
346        final int lostFocusUid = mTmpWindow.mOwnerUid;
347        final Handler handler = mService.mH;
348        if (w.mAttrs.type == TYPE_TOAST && w.mOwnerUid == lostFocusUid) {
349            if (!handler.hasMessages(WINDOW_HIDE_TIMEOUT, w)) {
350                handler.sendMessageDelayed(handler.obtainMessage(WINDOW_HIDE_TIMEOUT, w),
351                        w.mAttrs.hideTimeoutMilliseconds);
352            }
353        }
354    };
355
356    private final ToBooleanFunction<WindowState> mFindFocusedWindow = w -> {
357        final AppWindowToken focusedApp = mService.mFocusedApp;
358        if (DEBUG_FOCUS) Slog.v(TAG_WM, "Looking for focus: " + w
359                + ", flags=" + w.mAttrs.flags + ", canReceive=" + w.canReceiveKeys());
360
361        if (!w.canReceiveKeys()) {
362            return false;
363        }
364
365        final AppWindowToken wtoken = w.mAppToken;
366
367        // If this window's application has been removed, just skip it.
368        if (wtoken != null && (wtoken.removed || wtoken.sendingToBottom)) {
369            if (DEBUG_FOCUS) Slog.v(TAG_WM, "Skipping " + wtoken + " because "
370                    + (wtoken.removed ? "removed" : "sendingToBottom"));
371            return false;
372        }
373
374        if (focusedApp == null) {
375            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp=null"
376                    + " using new focus @ " + w);
377            mTmpWindow = w;
378            return true;
379        }
380
381        if (!focusedApp.windowsAreFocusable()) {
382            // Current focused app windows aren't focusable...
383            if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: focusedApp windows not"
384                    + " focusable using new focus @ " + w);
385            mTmpWindow = w;
386            return true;
387        }
388
389        // Descend through all of the app tokens and find the first that either matches
390        // win.mAppToken (return win) or mFocusedApp (return null).
391        if (wtoken != null && w.mAttrs.type != TYPE_APPLICATION_STARTING) {
392            if (focusedApp.compareTo(wtoken) > 0) {
393                // App stack below focused app stack. No focus for you!!!
394                if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM,
395                        "findFocusedWindow: Reached focused app=" + focusedApp);
396                mTmpWindow = null;
397                return true;
398            }
399        }
400
401        if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "findFocusedWindow: Found new focus @ " + w);
402        mTmpWindow = w;
403        return true;
404    };
405
406    private final Consumer<WindowState> mPrepareWindowSurfaces =
407            w -> w.mWinAnimator.prepareSurfaceLocked(true);
408
409    private final Consumer<WindowState> mPerformLayout = w -> {
410        // Don't do layout of a window if it is not visible, or soon won't be visible, to avoid
411        // wasting time and funky changes while a window is animating away.
412        final boolean gone = (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w))
413                || w.isGoneForLayoutLw();
414
415        if (DEBUG_LAYOUT && !w.mLayoutAttached) {
416            Slog.v(TAG, "1ST PASS " + w + ": gone=" + gone + " mHaveFrame=" + w.mHaveFrame
417                    + " mLayoutAttached=" + w.mLayoutAttached
418                    + " screen changed=" + w.isConfigChanged());
419            final AppWindowToken atoken = w.mAppToken;
420            if (gone) Slog.v(TAG, "  GONE: mViewVisibility=" + w.mViewVisibility
421                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
422                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
423                    + " parentHidden=" + w.isParentWindowHidden());
424            else Slog.v(TAG, "  VIS: mViewVisibility=" + w.mViewVisibility
425                    + " mRelayoutCalled=" + w.mRelayoutCalled + " hidden=" + w.mToken.hidden
426                    + " hiddenRequested=" + (atoken != null && atoken.hiddenRequested)
427                    + " parentHidden=" + w.isParentWindowHidden());
428        }
429
430        // If this view is GONE, then skip it -- keep the current frame, and let the caller know
431        // so they can ignore it if they want.  (We do the normal layout for INVISIBLE windows,
432        // since that means "perform layout as normal, just don't display").
433        if (!gone || !w.mHaveFrame || w.mLayoutNeeded
434                || ((w.isConfigChanged() || w.setReportResizeHints())
435                && !w.isGoneForLayoutLw() &&
436                ((w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
437                        (w.mHasSurface && w.mAppToken != null &&
438                                w.mAppToken.layoutConfigChanges)))) {
439            if (!w.mLayoutAttached) {
440                if (mTmpInitial) {
441                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
442                    w.mContentChanged = false;
443                }
444                if (w.mAttrs.type == TYPE_DREAM) {
445                    // Don't layout windows behind a dream, so that if it does stuff like hide
446                    // the status bar we won't get a bad transition when it goes away.
447                    mTmpWindow = w;
448                }
449                w.mLayoutNeeded = false;
450                w.prelayout();
451                mService.mPolicy.layoutWindowLw(w, null);
452                w.mLayoutSeq = mService.mLayoutSeq;
453
454                // Window frames may have changed. Update dim layer with the new bounds.
455                final Task task = w.getTask();
456                if (task != null) {
457                    mDimLayerController.updateDimLayer(task);
458                }
459
460                if (DEBUG_LAYOUT) Slog.v(TAG, "  LAYOUT: mFrame=" + w.mFrame
461                        + " mContainingFrame=" + w.mContainingFrame
462                        + " mDisplayFrame=" + w.mDisplayFrame);
463            }
464        }
465    };
466
467    private final Consumer<WindowState> mPerformLayoutAttached = w -> {
468        if (w.mLayoutAttached) {
469            if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
470                    + " mViewVisibility=" + w.mViewVisibility
471                    + " mRelayoutCalled=" + w.mRelayoutCalled);
472            // If this view is GONE, then skip it -- keep the current frame, and let the caller
473            // know so they can ignore it if they want.  (We do the normal layout for INVISIBLE
474            // windows, since that means "perform layout as normal, just don't display").
475            if (mTmpWindow != null && mService.mPolicy.canBeHiddenByKeyguardLw(w)) {
476                return;
477            }
478            if ((w.mViewVisibility != GONE && w.mRelayoutCalled) || !w.mHaveFrame
479                    || w.mLayoutNeeded) {
480                if (mTmpInitial) {
481                    //Slog.i(TAG, "Window " + this + " clearing mContentChanged - initial");
482                    w.mContentChanged = false;
483                }
484                w.mLayoutNeeded = false;
485                w.prelayout();
486                mService.mPolicy.layoutWindowLw(w, w.getParentWindow());
487                w.mLayoutSeq = mService.mLayoutSeq;
488                if (DEBUG_LAYOUT) Slog.v(TAG, " LAYOUT: mFrame=" + w.mFrame
489                        + " mContainingFrame=" + w.mContainingFrame
490                        + " mDisplayFrame=" + w.mDisplayFrame);
491            }
492        } else if (w.mAttrs.type == TYPE_DREAM) {
493            // Don't layout windows behind a dream, so that if it does stuff like hide the
494            // status bar we won't get a bad transition when it goes away.
495            mTmpWindow = mTmpWindow2;
496        }
497    };
498
499    private final Predicate<WindowState> mComputeImeTargetPredicate = w -> {
500        if (DEBUG_INPUT_METHOD && mUpdateImeTarget) Slog.i(TAG_WM, "Checking window @" + w
501                + " fl=0x" + Integer.toHexString(w.mAttrs.flags));
502        return w.canBeImeTarget();
503    };
504
505    private final Consumer<WindowState> mApplyPostLayoutPolicy =
506            w -> mService.mPolicy.applyPostLayoutPolicyLw(w, w.mAttrs, w.getParentWindow(),
507                    mService.mInputMethodTarget);
508
509    private final Consumer<WindowState> mApplySurfaceChangesTransaction = w -> {
510        final WindowSurfacePlacer surfacePlacer = mService.mWindowPlacerLocked;
511        final boolean obscuredChanged = w.mObscured !=
512                mTmpApplySurfaceChangesTransactionState.obscured;
513        final RootWindowContainer root = mService.mRoot;
514        // Only used if default window
515        final boolean someoneLosingFocus = !mService.mLosingFocus.isEmpty();
516
517        // Update effect.
518        w.mObscured = mTmpApplySurfaceChangesTransactionState.obscured;
519        if (!mTmpApplySurfaceChangesTransactionState.obscured) {
520            final boolean isDisplayed = w.isDisplayedLw();
521
522            if (isDisplayed && w.isObscuringDisplay()) {
523                // This window completely covers everything behind it, so we want to leave all
524                // of them as undimmed (for performance reasons).
525                root.mObscuringWindow = w;
526                mTmpApplySurfaceChangesTransactionState.obscured = true;
527            }
528
529            mTmpApplySurfaceChangesTransactionState.displayHasContent |=
530                    root.handleNotObscuredLocked(w,
531                            mTmpApplySurfaceChangesTransactionState.obscured,
532                            mTmpApplySurfaceChangesTransactionState.syswin);
533
534            if (w.mHasSurface && isDisplayed) {
535                final int type = w.mAttrs.type;
536                if (type == TYPE_SYSTEM_DIALOG || type == TYPE_SYSTEM_ERROR
537                        || (w.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
538                    mTmpApplySurfaceChangesTransactionState.syswin = true;
539                }
540                if (mTmpApplySurfaceChangesTransactionState.preferredRefreshRate == 0
541                        && w.mAttrs.preferredRefreshRate != 0) {
542                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate
543                            = w.mAttrs.preferredRefreshRate;
544                }
545                if (mTmpApplySurfaceChangesTransactionState.preferredModeId == 0
546                        && w.mAttrs.preferredDisplayModeId != 0) {
547                    mTmpApplySurfaceChangesTransactionState.preferredModeId
548                            = w.mAttrs.preferredDisplayModeId;
549                }
550            }
551        }
552
553        w.applyDimLayerIfNeeded();
554
555        if (isDefaultDisplay && obscuredChanged && w.isVisibleLw()
556                && mWallpaperController.isWallpaperTarget(w)) {
557            // This is the wallpaper target and its obscured state changed... make sure the
558            // current wallpaper's visibility has been updated accordingly.
559            mWallpaperController.updateWallpaperVisibility();
560        }
561
562        w.handleWindowMovedIfNeeded();
563
564        final WindowStateAnimator winAnimator = w.mWinAnimator;
565
566        //Slog.i(TAG, "Window " + this + " clearing mContentChanged - done placing");
567        w.mContentChanged = false;
568
569        // Moved from updateWindowsAndWallpaperLocked().
570        if (w.mHasSurface) {
571            // Take care of the window being ready to display.
572            final boolean committed = winAnimator.commitFinishDrawingLocked();
573            if (isDefaultDisplay && committed) {
574                if (w.mAttrs.type == TYPE_DREAM) {
575                    // HACK: When a dream is shown, it may at that point hide the lock screen.
576                    // So we need to redo the layout to let the phone window manager make this
577                    // happen.
578                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT;
579                    if (DEBUG_LAYOUT_REPEATS) {
580                        surfacePlacer.debugLayoutRepeats(
581                                "dream and commitFinishDrawingLocked true",
582                                pendingLayoutChanges);
583                    }
584                }
585                if ((w.mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
586                    if (DEBUG_WALLPAPER_LIGHT) Slog.v(TAG,
587                            "First draw done in potential wallpaper target " + w);
588                    root.mWallpaperMayChange = true;
589                    pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
590                    if (DEBUG_LAYOUT_REPEATS) {
591                        surfacePlacer.debugLayoutRepeats(
592                                "wallpaper and commitFinishDrawingLocked true",
593                                pendingLayoutChanges);
594                    }
595                }
596            }
597            if (!winAnimator.isAnimationStarting() && !winAnimator.isWaitingForOpening()) {
598                // Updates the shown frame before we set up the surface. This is needed
599                // because the resizing could change the top-left position (in addition to
600                // size) of the window. setSurfaceBoundariesLocked uses mShownPosition to
601                // position the surface.
602                //
603                // If an animation is being started, we can't call this method because the
604                // animation hasn't processed its initial transformation yet, but in general
605                // we do want to update the position if the window is animating.
606                winAnimator.computeShownFrameLocked();
607            }
608            winAnimator.setSurfaceBoundariesLocked(mTmpRecoveringMemory /* recoveringMemory */);
609        }
610
611        final AppWindowToken atoken = w.mAppToken;
612        if (atoken != null) {
613            final boolean updateAllDrawn = atoken.updateDrawnWindowStates(w);
614            if (updateAllDrawn && !mTmpUpdateAllDrawn.contains(atoken)) {
615                mTmpUpdateAllDrawn.add(atoken);
616            }
617        }
618
619        if (isDefaultDisplay && someoneLosingFocus && w == mService.mCurrentFocus
620                && w.isDisplayedLw()) {
621            mTmpApplySurfaceChangesTransactionState.focusDisplayed = true;
622        }
623
624        w.updateResizingWindowIfNeeded();
625    };
626
627    /**
628     * @param display May not be null.
629     * @param service You know.
630     * @param layersController window layer controller used to assign layer to the windows on this
631     *                         display.
632     * @param wallpaperController wallpaper windows controller used to adjust the positioning of the
633     *                            wallpaper windows in the window list.
634     */
635    DisplayContent(Display display, WindowManagerService service,
636            WindowLayersController layersController, WallpaperController wallpaperController) {
637        mDisplay = display;
638        mDisplayId = display.getDisplayId();
639        mLayersController = layersController;
640        mWallpaperController = wallpaperController;
641        display.getDisplayInfo(mDisplayInfo);
642        display.getMetrics(mDisplayMetrics);
643        isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
644        mService = service;
645        initializeDisplayBaseInfo();
646        mDividerControllerLocked = new DockedStackDividerController(service, this);
647        mPinnedStackControllerLocked = new PinnedStackController(service, this);
648        mDimLayerController = new DimLayerController(this);
649
650        // These are the only direct children we should ever have and they are permanent.
651        super.addChild(mBelowAppWindowsContainers, null);
652        super.addChild(mTaskStackContainers, null);
653        super.addChild(mAboveAppWindowsContainers, null);
654        super.addChild(mImeWindowsContainers, null);
655    }
656
657    int getDisplayId() {
658        return mDisplayId;
659    }
660
661    WindowToken getWindowToken(IBinder binder) {
662        return mTokenMap.get(binder);
663    }
664
665    AppWindowToken getAppWindowToken(IBinder binder) {
666        final WindowToken token = getWindowToken(binder);
667        if (token == null) {
668            return null;
669        }
670        return token.asAppWindowToken();
671    }
672
673    void addWindowToken(IBinder binder, WindowToken token) {
674        final DisplayContent dc = mService.mRoot.getWindowTokenDisplay(token);
675        if (dc != null) {
676            // We currently don't support adding a window token to the display if the display
677            // already has the binder mapped to another token. If there is a use case for supporting
678            // this moving forward we will either need to merge the WindowTokens some how or have
679            // the binder map to a list of window tokens.
680            throw new IllegalArgumentException("Can't map token=" + token + " to display=" + this
681                    + " already mapped to display=" + dc + " tokens=" + dc.mTokenMap);
682        }
683        mTokenMap.put(binder, token);
684
685        if (token.asAppWindowToken() == null) {
686            // Add non-app token to container hierarchy on the display. App tokens are added through
687            // the parent container managing them (e.g. Tasks).
688            switch (token.windowType) {
689                case TYPE_WALLPAPER:
690                    mBelowAppWindowsContainers.addChild(token);
691                    break;
692                case TYPE_INPUT_METHOD:
693                case TYPE_INPUT_METHOD_DIALOG:
694                    mImeWindowsContainers.addChild(token);
695                    break;
696                default:
697                    mAboveAppWindowsContainers.addChild(token);
698                    break;
699            }
700        }
701    }
702
703    WindowToken removeWindowToken(IBinder binder) {
704        final WindowToken token = mTokenMap.remove(binder);
705        if (token != null && token.asAppWindowToken() == null) {
706            token.setExiting();
707        }
708        return token;
709    }
710
711    /** Changes the display the input window token is housed on to this one. */
712    void reParentWindowToken(WindowToken token) {
713        final DisplayContent prevDc = token.getDisplayContent();
714        if (prevDc == this) {
715            return;
716        }
717        if (prevDc != null && prevDc.mTokenMap.remove(token.token) != null
718                && token.asAppWindowToken() == null) {
719            // Removed the token from the map, but made sure it's not an app token before removing
720            // from parent.
721            token.getParent().removeChild(token);
722        }
723
724        addWindowToken(token.token, token);
725    }
726
727    void removeAppToken(IBinder binder) {
728        final WindowToken token = removeWindowToken(binder);
729        if (token == null) {
730            Slog.w(TAG_WM, "removeAppToken: Attempted to remove non-existing token: " + binder);
731            return;
732        }
733
734        final AppWindowToken appToken = token.asAppWindowToken();
735
736        if (appToken == null) {
737            Slog.w(TAG_WM, "Attempted to remove non-App token: " + binder + " token=" + token);
738            return;
739        }
740
741        appToken.onRemovedFromDisplay();
742    }
743
744    Display getDisplay() {
745        return mDisplay;
746    }
747
748    DisplayInfo getDisplayInfo() {
749        return mDisplayInfo;
750    }
751
752    DisplayMetrics getDisplayMetrics() {
753        return mDisplayMetrics;
754    }
755
756    DockedStackDividerController getDockedDividerController() {
757        return mDividerControllerLocked;
758    }
759
760    PinnedStackController getPinnedStackController() {
761        return mPinnedStackControllerLocked;
762    }
763
764    /**
765     * Returns true if the specified UID has access to this display.
766     */
767    boolean hasAccess(int uid) {
768        return mDisplay.hasAccess(uid);
769    }
770
771    boolean isPrivate() {
772        return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
773    }
774
775    TaskStack getHomeStack() {
776        if (mHomeStack == null && mDisplayId == DEFAULT_DISPLAY) {
777            Slog.e(TAG_WM, "getHomeStack: Returning null from this=" + this);
778        }
779        return mHomeStack;
780    }
781
782    TaskStack getStackById(int stackId) {
783        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
784            final TaskStack stack = mTaskStackContainers.get(i);
785            if (stack.mStackId == stackId) {
786                return stack;
787            }
788        }
789        return null;
790    }
791
792    @Override
793    void onConfigurationChanged(Configuration newParentConfig) {
794        super.onConfigurationChanged(newParentConfig);
795
796        // The display size information is heavily dependent on the resources in the current
797        // configuration, so we need to reconfigure it every time the configuration changes.
798        // See {@link PhoneWindowManager#setInitialDisplaySize}...sigh...
799        mService.reconfigureDisplayLocked(this);
800
801        getDockedDividerController().onConfigurationChanged();
802        getPinnedStackController().onConfigurationChanged();
803    }
804
805    /**
806     * Callback used to trigger bounds update after configuration change and get ids of stacks whose
807     * bounds were updated.
808     */
809    void updateStackBoundsAfterConfigChange(@NonNull List<Integer> changedStackList) {
810        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
811            final TaskStack stack = mTaskStackContainers.get(i);
812            if (stack.updateBoundsAfterConfigChange()) {
813                changedStackList.add(stack.mStackId);
814            }
815        }
816    }
817
818    @Override
819    boolean fillsParent() {
820        return true;
821    }
822
823    @Override
824    boolean isVisible() {
825        return true;
826    }
827
828    @Override
829    void onAppTransitionDone() {
830        super.onAppTransitionDone();
831        mService.mWindowsChanged = true;
832    }
833
834    @Override
835    boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
836        // Special handling so we can process IME windows with #forAllImeWindows above their IME
837        // target, or here in order if there isn't an IME target.
838        if (traverseTopToBottom) {
839            for (int i = mChildren.size() - 1; i >= 0; --i) {
840                final DisplayChildWindowContainer child = mChildren.get(i);
841                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
842                    // In this case the Ime windows will be processed above their target so we skip
843                    // here.
844                    continue;
845                }
846                if (child.forAllWindows(callback, traverseTopToBottom)) {
847                    return true;
848                }
849            }
850        } else {
851            final int count = mChildren.size();
852            for (int i = 0; i < count; i++) {
853                final DisplayChildWindowContainer child = mChildren.get(i);
854                if (child == mImeWindowsContainers && mService.mInputMethodTarget != null) {
855                    // In this case the Ime windows will be processed above their target so we skip
856                    // here.
857                    continue;
858                }
859                if (child.forAllWindows(callback, traverseTopToBottom)) {
860                    return true;
861                }
862            }
863        }
864        return false;
865    }
866
867    boolean forAllImeWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
868        return mImeWindowsContainers.forAllWindows(callback, traverseTopToBottom);
869    }
870
871    @Override
872    int getOrientation() {
873        final WindowManagerPolicy policy = mService.mPolicy;
874
875        if (mService.mDisplayFrozen) {
876            if (mService.mLastWindowForcedOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
877                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
878                        "Display is frozen, return " + mService.mLastWindowForcedOrientation);
879                // If the display is frozen, some activities may be in the middle of restarting, and
880                // thus have removed their old window. If the window has the flag to hide the lock
881                // screen, then the lock screen can re-appear and inflict its own orientation on us.
882                // Keep the orientation stable until this all settles down.
883                return mService.mLastWindowForcedOrientation;
884            } else if (policy.isKeyguardLocked()) {
885                // Use the last orientation the while the display is frozen with the keyguard
886                // locked. This could be the keyguard forced orientation or from a SHOW_WHEN_LOCKED
887                // window. We don't want to check the show when locked window directly though as
888                // things aren't stable while the display is frozen, for example the window could be
889                // momentarily unavailable due to activity relaunch.
890                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, "Display is frozen while keyguard locked, "
891                        + "return " + mService.mLastOrientation);
892                return mService.mLastOrientation;
893            }
894        } else {
895            final int orientation = mAboveAppWindowsContainers.getOrientation();
896            if (orientation != SCREEN_ORIENTATION_UNSET) {
897                return orientation;
898            }
899        }
900
901        // Top system windows are not requesting an orientation. Start searching from apps.
902        return mTaskStackContainers.getOrientation();
903    }
904
905    void updateDisplayInfo() {
906        mDisplay.getDisplayInfo(mDisplayInfo);
907        mDisplay.getMetrics(mDisplayMetrics);
908        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
909            mTaskStackContainers.get(i).updateDisplayInfo(null);
910        }
911    }
912
913    void initializeDisplayBaseInfo() {
914        final DisplayManagerInternal displayManagerInternal = mService.mDisplayManagerInternal;
915        if (displayManagerInternal != null) {
916            // Bootstrap the default logical display from the display manager.
917            final DisplayInfo newDisplayInfo = displayManagerInternal.getDisplayInfo(mDisplayId);
918            if (newDisplayInfo != null) {
919                mDisplayInfo.copyFrom(newDisplayInfo);
920            }
921        }
922
923        mBaseDisplayWidth = mInitialDisplayWidth = mDisplayInfo.logicalWidth;
924        mBaseDisplayHeight = mInitialDisplayHeight = mDisplayInfo.logicalHeight;
925        mBaseDisplayDensity = mInitialDisplayDensity = mDisplayInfo.logicalDensityDpi;
926        mBaseDisplayRect.set(0, 0, mBaseDisplayWidth, mBaseDisplayHeight);
927    }
928
929    void getLogicalDisplayRect(Rect out) {
930        // Uses same calculation as in LogicalDisplay#configureDisplayInTransactionLocked.
931        final int orientation = mDisplayInfo.rotation;
932        boolean rotated = (orientation == ROTATION_90 || orientation == ROTATION_270);
933        final int physWidth = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;
934        final int physHeight = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;
935        int width = mDisplayInfo.logicalWidth;
936        int left = (physWidth - width) / 2;
937        int height = mDisplayInfo.logicalHeight;
938        int top = (physHeight - height) / 2;
939        out.set(left, top, left + width, top + height);
940    }
941
942    private void getLogicalDisplayRect(Rect out, int orientation) {
943        getLogicalDisplayRect(out);
944
945        // Rotate the Rect if needed.
946        final int currentRotation = mDisplayInfo.rotation;
947        final int rotationDelta = deltaRotation(currentRotation, orientation);
948        if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
949            createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix);
950            mTmpRectF.set(out);
951            mTmpMatrix.mapRect(mTmpRectF);
952            mTmpRectF.round(out);
953        }
954    }
955
956    void getContentRect(Rect out) {
957        out.set(mContentRect);
958    }
959
960    /**
961     * Adds the stack to this display.
962     * @see WindowManagerService#addStackToDisplay(int, int, boolean)
963     */
964    Rect addStackToDisplay(int stackId, boolean onTop) {
965        boolean attachedToDisplay = false;
966        TaskStack stack = mService.mStackIdToStack.get(stackId);
967        if (stack == null) {
968            if (DEBUG_STACK) Slog.d(TAG_WM, "Create new stackId=" + stackId + " on displayId="
969                    + mDisplayId);
970
971            stack = getStackById(stackId);
972            if (stack != null) {
973                // It's already attached to the display...clear mDeferRemoval and move stack to
974                // appropriate z-order on display as needed.
975                stack.mDeferRemoval = false;
976                // We're not moving the display to front when we're adding stacks, only when
977                // requested to change the position of stack explicitly.
978                mTaskStackContainers.positionChildAt(onTop ? POSITION_TOP : POSITION_BOTTOM, stack,
979                        false /* includingParents */);
980                attachedToDisplay = true;
981            } else {
982                stack = new TaskStack(mService, stackId);
983            }
984
985            mService.mStackIdToStack.put(stackId, stack);
986            if (stackId == DOCKED_STACK_ID) {
987                mDividerControllerLocked.notifyDockedStackExistsChanged(true);
988            }
989        } else {
990            final DisplayContent currentDC = stack.getDisplayContent();
991            if (currentDC != null) {
992                throw new IllegalStateException("Trying to add stackId=" + stackId
993                        + "to displayId=" + mDisplayId + ", but it's already attached to displayId="
994                        + currentDC.getDisplayId());
995            }
996        }
997
998        if (!attachedToDisplay) {
999            mTaskStackContainers.addStackToDisplay(stack, onTop);
1000        }
1001
1002        if (stack.getRawFullscreen()) {
1003            return null;
1004        }
1005        final Rect bounds = new Rect();
1006        stack.getRawBounds(bounds);
1007        return bounds;
1008    }
1009
1010    /** Removes the stack from the display and prepares for changing the parent. */
1011    private void removeStackFromDisplay(TaskStack stack) {
1012        mTaskStackContainers.removeStackFromDisplay(stack);
1013    }
1014
1015    /** Moves the stack to this display and returns the updated bounds. */
1016    Rect moveStackToDisplay(TaskStack stack) {
1017        final DisplayContent currentDisplayContent = stack.getDisplayContent();
1018        if (currentDisplayContent == null) {
1019            throw new IllegalStateException("Trying to move stackId=" + stack.mStackId
1020                    + " which is not currently attached to any display");
1021        }
1022        if (stack.getDisplayContent().getDisplayId() == mDisplayId) {
1023            throw new IllegalArgumentException("Trying to move stackId=" + stack.mStackId
1024                    + " to its current displayId=" + mDisplayId);
1025        }
1026
1027        currentDisplayContent.removeStackFromDisplay(stack);
1028        return addStackToDisplay(stack.mStackId, true /* onTop */);
1029    }
1030
1031    @Override
1032    protected void addChild(DisplayChildWindowContainer child,
1033            Comparator<DisplayChildWindowContainer> comparator) {
1034        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1035    }
1036
1037    @Override
1038    protected void addChild(DisplayChildWindowContainer child, int index) {
1039        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1040    }
1041
1042    @Override
1043    protected void removeChild(DisplayChildWindowContainer child) {
1044        // Only allow removal of direct children from this display if the display is in the process
1045        // of been removed.
1046        if (mRemovingDisplay) {
1047            super.removeChild(child);
1048            return;
1049        }
1050        throw new UnsupportedOperationException("See DisplayChildWindowContainer");
1051    }
1052
1053    @Override
1054    void positionChildAt(int position, DisplayChildWindowContainer child, boolean includingParents) {
1055        // Children of the display are statically ordered, so the real intention here is to perform
1056        // the operation on the display and not the static direct children.
1057        getParent().positionChildAt(position, this, includingParents);
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     * @param includeDecor whether to include window decors, like the status or navigation bar
2108     *                     background of the window
2109     */
2110    Bitmap screenshotApplications(IBinder appToken, int width, int height,
2111            boolean includeFullDisplay, float frameScale, Bitmap.Config config,
2112            boolean wallpaperOnly, boolean includeDecor) {
2113        Bitmap bitmap = screenshotApplications(appToken, width, height, includeFullDisplay,
2114                frameScale, wallpaperOnly, includeDecor, SurfaceControl::screenshot);
2115
2116        if (DEBUG_SCREENSHOT) {
2117            // TEST IF IT's ALL BLACK
2118            int[] buffer = new int[bitmap.getWidth() * bitmap.getHeight()];
2119            bitmap.getPixels(buffer, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(),
2120                    bitmap.getHeight());
2121            boolean allBlack = true;
2122            final int firstColor = buffer[0];
2123            for (int i = 0; i < buffer.length; i++) {
2124                if (buffer[i] != firstColor) {
2125                    allBlack = false;
2126                    break;
2127                }
2128            }
2129            if (allBlack) {
2130                final WindowState appWin = mScreenshotApplicationState.appWin;
2131                final int maxLayer = mScreenshotApplicationState.maxLayer;
2132                final int minLayer = mScreenshotApplicationState.minLayer;
2133                Slog.i(TAG_WM, "Screenshot " + appWin + " was monochrome(" +
2134                        Integer.toHexString(firstColor) + ")! mSurfaceLayer=" +
2135                        (appWin != null ?
2136                                appWin.mWinAnimator.mSurfaceController.getLayer() : "null") +
2137                        " minLayer=" + minLayer + " maxLayer=" + maxLayer);
2138            }
2139        }
2140
2141        // Create a copy of the screenshot that is immutable and backed in ashmem.
2142        // This greatly reduces the overhead of passing the bitmap between processes.
2143        Bitmap ret = bitmap.createAshmemBitmap(config);
2144        bitmap.recycle();
2145        return ret;
2146    }
2147
2148    GraphicBuffer screenshotApplicationsToBuffer(IBinder appToken, int width, int height,
2149            boolean includeFullDisplay, float frameScale, boolean wallpaperOnly,
2150            boolean includeDecor) {
2151        return screenshotApplications(appToken, width, height, includeFullDisplay, frameScale,
2152                wallpaperOnly, includeDecor, SurfaceControl::screenshotToBuffer);
2153    }
2154
2155    private <E> E screenshotApplications(IBinder appToken, int width, int height,
2156            boolean includeFullDisplay, float frameScale, boolean wallpaperOnly,
2157            boolean includeDecor, Screenshoter<E> screenshoter) {
2158        int dw = mDisplayInfo.logicalWidth;
2159        int dh = mDisplayInfo.logicalHeight;
2160        if (dw == 0 || dh == 0) {
2161            if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2162                    + ": returning null. logical widthxheight=" + dw + "x" + dh);
2163            return null;
2164        }
2165
2166        E bitmap;
2167
2168        mScreenshotApplicationState.reset(appToken == null && !wallpaperOnly);
2169        final Rect frame = new Rect();
2170        final Rect stackBounds = new Rect();
2171
2172        boolean includeImeInScreenshot;
2173        synchronized(mService.mWindowMap) {
2174            final AppWindowToken imeTargetAppToken = mService.mInputMethodTarget != null
2175                    ? mService.mInputMethodTarget.mAppToken : null;
2176            // We only include the Ime in the screenshot if the app we are screenshoting is the IME
2177            // target and isn't in multi-window mode. We don't screenshot the IME in multi-window
2178            // mode because the frame of the IME might not overlap with that of the app.
2179            // E.g. IME target app at the top in split-screen mode and the IME at the bottom
2180            // overlapping with the bottom app.
2181            includeImeInScreenshot = imeTargetAppToken != null
2182                    && imeTargetAppToken.appToken != null
2183                    && imeTargetAppToken.appToken.asBinder() == appToken
2184                    && !mService.mInputMethodTarget.isInMultiWindowMode();
2185        }
2186
2187        final int aboveAppLayer = (mService.mPolicy.windowTypeToLayerLw(TYPE_APPLICATION) + 1)
2188                * TYPE_LAYER_MULTIPLIER + TYPE_LAYER_OFFSET;
2189        final MutableBoolean mutableIncludeFullDisplay = new MutableBoolean(includeFullDisplay);
2190        synchronized(mService.mWindowMap) {
2191            // Figure out the part of the screen that is actually the app.
2192            mScreenshotApplicationState.appWin = null;
2193            forAllWindows(w -> {
2194                if (!w.mHasSurface) {
2195                    return false;
2196                }
2197                if (w.mLayer >= aboveAppLayer) {
2198                    return false;
2199                }
2200                if (wallpaperOnly && !w.mIsWallpaper) {
2201                    return false;
2202                }
2203                if (w.mIsImWindow) {
2204                    if (!includeImeInScreenshot) {
2205                        return false;
2206                    }
2207                } else if (w.mIsWallpaper) {
2208                    // If this is the wallpaper layer and we're only looking for the wallpaper layer
2209                    // then the target window state is this one.
2210                    if (wallpaperOnly) {
2211                        mScreenshotApplicationState.appWin = w;
2212                    }
2213
2214                    if (mScreenshotApplicationState.appWin == null) {
2215                        // We have not ran across the target window yet, so it is probably behind
2216                        // the wallpaper. This can happen when the keyguard is up and all windows
2217                        // are moved behind the wallpaper. We don't want to include the wallpaper
2218                        // layer in the screenshot as it will cover-up the layer of the target
2219                        // window.
2220                        return false;
2221                    }
2222                    // Fall through. The target window is in front of the wallpaper. For this
2223                    // case we want to include the wallpaper layer in the screenshot because
2224                    // the target window might have some transparent areas.
2225                } else if (appToken != null) {
2226                    if (w.mAppToken == null || w.mAppToken.token != appToken) {
2227                        // This app window is of no interest if it is not associated with the
2228                        // screenshot app.
2229                        return false;
2230                    }
2231                    mScreenshotApplicationState.appWin = w;
2232                }
2233
2234                // Include this window.
2235
2236                final WindowStateAnimator winAnim = w.mWinAnimator;
2237                int layer = winAnim.mSurfaceController.getLayer();
2238                if (mScreenshotApplicationState.maxLayer < layer) {
2239                    mScreenshotApplicationState.maxLayer = layer;
2240                }
2241                if (mScreenshotApplicationState.minLayer > layer) {
2242                    mScreenshotApplicationState.minLayer = layer;
2243                }
2244
2245                // Don't include wallpaper in bounds calculation
2246                if (includeDecor && !stackBounds.isEmpty()) {
2247                    frame.set(stackBounds);
2248                } else if (includeDecor) {
2249                    mutableIncludeFullDisplay.value = true;
2250                } else if (!mutableIncludeFullDisplay.value && !w.mIsWallpaper) {
2251                    final Rect wf = w.mFrame;
2252                    final Rect cr = w.mContentInsets;
2253                    int left = wf.left + cr.left;
2254                    int top = wf.top + cr.top;
2255                    int right = wf.right - cr.right;
2256                    int bottom = wf.bottom - cr.bottom;
2257                    frame.union(left, top, right, bottom);
2258                    w.getVisibleBounds(stackBounds);
2259                    if (!Rect.intersects(frame, stackBounds)) {
2260                        // Set frame empty if there's no intersection.
2261                        frame.setEmpty();
2262                    }
2263                }
2264
2265                final boolean foundTargetWs =
2266                        (w.mAppToken != null && w.mAppToken.token == appToken)
2267                                || (mScreenshotApplicationState.appWin != null && wallpaperOnly);
2268                if (foundTargetWs && w.isDisplayedLw() && winAnim.getShown()) {
2269                    mScreenshotApplicationState.screenshotReady = true;
2270                }
2271
2272                if (w.isObscuringDisplay()){
2273                    return true;
2274                }
2275                return false;
2276            }, true /* traverseTopToBottom */);
2277
2278            final WindowState appWin = mScreenshotApplicationState.appWin;
2279            final boolean screenshotReady = mScreenshotApplicationState.screenshotReady;
2280            final int maxLayer = mScreenshotApplicationState.maxLayer;
2281            final int minLayer = mScreenshotApplicationState.minLayer;
2282
2283            if (appToken != null && appWin == null) {
2284                // Can't find a window to snapshot.
2285                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM,
2286                        "Screenshot: Couldn't find a surface matching " + appToken);
2287                return null;
2288            }
2289
2290            if (!screenshotReady) {
2291                Slog.i(TAG_WM, "Failed to capture screenshot of " + appToken +
2292                        " appWin=" + (appWin == null ? "null" : (appWin + " drawState=" +
2293                        appWin.mWinAnimator.mDrawState)));
2294                return null;
2295            }
2296
2297            // Screenshot is ready to be taken. Everything from here below will continue
2298            // through the bottom of the loop and return a value. We only stay in the loop
2299            // because we don't want to release the mWindowMap lock until the screenshot is
2300            // taken.
2301
2302            if (maxLayer == 0) {
2303                if (DEBUG_SCREENSHOT) Slog.i(TAG_WM, "Screenshot of " + appToken
2304                        + ": returning null maxLayer=" + maxLayer);
2305                return null;
2306            }
2307
2308            if (!mutableIncludeFullDisplay.value) {
2309                // Constrain frame to the screen size.
2310                if (!frame.intersect(0, 0, dw, dh)) {
2311                    frame.setEmpty();
2312                }
2313            } else {
2314                // Caller just wants entire display.
2315                frame.set(0, 0, dw, dh);
2316            }
2317            if (frame.isEmpty()) {
2318                return null;
2319            }
2320
2321            if (width < 0) {
2322                width = (int) (frame.width() * frameScale);
2323            }
2324            if (height < 0) {
2325                height = (int) (frame.height() * frameScale);
2326            }
2327
2328            // Tell surface flinger what part of the image to crop. Take the top
2329            // right part of the application, and crop the larger dimension to fit.
2330            Rect crop = new Rect(frame);
2331            if (width / (float) frame.width() < height / (float) frame.height()) {
2332                int cropWidth = (int)((float)width / (float)height * frame.height());
2333                crop.right = crop.left + cropWidth;
2334            } else {
2335                int cropHeight = (int)((float)height / (float)width * frame.width());
2336                crop.bottom = crop.top + cropHeight;
2337            }
2338
2339            // The screenshot API does not apply the current screen rotation.
2340            int rot = mDisplay.getRotation();
2341
2342            if (rot == ROTATION_90 || rot == ROTATION_270) {
2343                rot = (rot == ROTATION_90) ? ROTATION_270 : ROTATION_90;
2344            }
2345
2346            // Surfaceflinger is not aware of orientation, so convert our logical
2347            // crop to surfaceflinger's portrait orientation.
2348            convertCropForSurfaceFlinger(crop, rot, dw, dh);
2349
2350            if (DEBUG_SCREENSHOT) {
2351                Slog.i(TAG_WM, "Screenshot: " + dw + "x" + dh + " from " + minLayer + " to "
2352                        + maxLayer + " appToken=" + appToken);
2353                forAllWindows(w -> {
2354                    final WindowSurfaceController controller = w.mWinAnimator.mSurfaceController;
2355                    Slog.i(TAG_WM, w + ": " + w.mLayer
2356                            + " animLayer=" + w.mWinAnimator.mAnimLayer
2357                            + " surfaceLayer=" + ((controller == null)
2358                            ? "null" : controller.getLayer()));
2359                }, false /* traverseTopToBottom */);
2360            }
2361
2362            final ScreenRotationAnimation screenRotationAnimation =
2363                    mService.mAnimator.getScreenRotationAnimationLocked(DEFAULT_DISPLAY);
2364            final boolean inRotation = screenRotationAnimation != null &&
2365                    screenRotationAnimation.isAnimating();
2366            if (DEBUG_SCREENSHOT && inRotation) Slog.v(TAG_WM,
2367                    "Taking screenshot while rotating");
2368
2369            // We force pending transactions to flush before taking
2370            // the screenshot by pushing an empty synchronous transaction.
2371            SurfaceControl.openTransaction();
2372            SurfaceControl.closeTransactionSync();
2373
2374            bitmap = screenshoter.screenshot(crop, width, height, minLayer, maxLayer,
2375                    inRotation, rot);
2376            if (bitmap == null) {
2377                Slog.w(TAG_WM, "Screenshot failure taking screenshot for (" + dw + "x" + dh
2378                        + ") to layer " + maxLayer);
2379                return null;
2380            }
2381        }
2382        return bitmap;
2383    }
2384
2385    // TODO: Can this use createRotationMatrix()?
2386    private static void convertCropForSurfaceFlinger(Rect crop, int rot, int dw, int dh) {
2387        if (rot == Surface.ROTATION_90) {
2388            final int tmp = crop.top;
2389            crop.top = dw - crop.right;
2390            crop.right = crop.bottom;
2391            crop.bottom = dw - crop.left;
2392            crop.left = tmp;
2393        } else if (rot == Surface.ROTATION_180) {
2394            int tmp = crop.top;
2395            crop.top = dh - crop.bottom;
2396            crop.bottom = dh - tmp;
2397            tmp = crop.right;
2398            crop.right = dw - crop.left;
2399            crop.left = dw - tmp;
2400        } else if (rot == Surface.ROTATION_270) {
2401            final int tmp = crop.top;
2402            crop.top = crop.left;
2403            crop.left = dh - crop.bottom;
2404            crop.bottom = crop.right;
2405            crop.right = dh - tmp;
2406        }
2407    }
2408
2409    void onSeamlessRotationTimeout() {
2410        // Used to indicate the layout is needed.
2411        mTmpWindow = null;
2412
2413        forAllWindows(w -> {
2414            if (!w.mSeamlesslyRotated) {
2415                return;
2416            }
2417            mTmpWindow = w;
2418            w.setDisplayLayoutNeeded();
2419            mService.markForSeamlessRotation(w, false);
2420        }, true /* traverseTopToBottom */);
2421
2422        if (mTmpWindow != null) {
2423            mService.mWindowPlacerLocked.performSurfacePlacement();
2424        }
2425    }
2426
2427    static final class TaskForResizePointSearchResult {
2428        boolean searchDone;
2429        Task taskForResize;
2430
2431        void reset() {
2432            searchDone = false;
2433            taskForResize = null;
2434        }
2435    }
2436
2437    private static final class ApplySurfaceChangesTransactionState {
2438        boolean displayHasContent;
2439        boolean obscured;
2440        boolean syswin;
2441        boolean focusDisplayed;
2442        float preferredRefreshRate;
2443        int preferredModeId;
2444
2445        void reset() {
2446            displayHasContent = false;
2447            obscured = false;
2448            syswin = false;
2449            focusDisplayed = false;
2450            preferredRefreshRate = 0;
2451            preferredModeId = 0;
2452        }
2453    }
2454
2455    private static final class ScreenshotApplicationState {
2456        WindowState appWin;
2457        int maxLayer;
2458        int minLayer;
2459        boolean screenshotReady;
2460
2461        void reset(boolean screenshotReady) {
2462            appWin = null;
2463            maxLayer = 0;
2464            minLayer = 0;
2465            this.screenshotReady = screenshotReady;
2466            minLayer = (screenshotReady) ? 0 : Integer.MAX_VALUE;
2467        }
2468    }
2469
2470    /**
2471     * Base class for any direct child window container of {@link #DisplayContent} need to inherit
2472     * from. This is mainly a pass through class that allows {@link #DisplayContent} to have
2473     * homogeneous children type which is currently required by sub-classes of
2474     * {@link WindowContainer} class.
2475     */
2476    static class DisplayChildWindowContainer<E extends WindowContainer> extends WindowContainer<E> {
2477
2478        int size() {
2479            return mChildren.size();
2480        }
2481
2482        E get(int index) {
2483            return mChildren.get(index);
2484        }
2485
2486        @Override
2487        boolean fillsParent() {
2488            return true;
2489        }
2490
2491        @Override
2492        boolean isVisible() {
2493            return true;
2494        }
2495    }
2496
2497    /**
2498     * Window container class that contains all containers on this display relating to Apps.
2499     * I.e Activities.
2500     */
2501    private final class TaskStackContainers extends DisplayChildWindowContainer<TaskStack> {
2502
2503        /**
2504         * Adds the stack to this container.
2505         * @see WindowManagerService#addStackToDisplay(int, int, boolean)
2506         */
2507        void addStackToDisplay(TaskStack stack, boolean onTop) {
2508            if (stack.mStackId == HOME_STACK_ID) {
2509                if (mHomeStack != null) {
2510                    throw new IllegalArgumentException("attachStack: HOME_STACK_ID (0) not first.");
2511                }
2512                mHomeStack = stack;
2513            }
2514            addChild(stack, onTop);
2515            stack.onDisplayChanged(DisplayContent.this);
2516        }
2517
2518        /** Removes the stack from its container and prepare for changing the parent. */
2519        void removeStackFromDisplay(TaskStack stack) {
2520            removeChild(stack);
2521            stack.onRemovedFromDisplay();
2522        }
2523
2524        private void addChild(TaskStack stack, boolean toTop) {
2525            final int addIndex = findPositionForStack(toTop ? mChildren.size() : 0, stack,
2526                    true /* adding */);
2527            addChild(stack, addIndex);
2528            setLayoutNeeded();
2529        }
2530
2531        @Override
2532        void positionChildAt(int position, TaskStack child, boolean includingParents) {
2533            if (StackId.isAlwaysOnTop(child.mStackId) && position != POSITION_TOP) {
2534                // This stack is always-on-top, override the default behavior.
2535                Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
2536
2537                // Moving to its current position, as we must call super but we don't want to
2538                // perform any meaningful action.
2539                final int currentPosition = mChildren.indexOf(child);
2540                super.positionChildAt(currentPosition, child, false /* includingParents */);
2541                return;
2542            }
2543
2544            final int targetPosition = findPositionForStack(position, child, false /* adding */);
2545            super.positionChildAt(targetPosition, child, includingParents);
2546
2547            setLayoutNeeded();
2548        }
2549
2550        /**
2551         * When stack is added or repositioned, find a proper position for it.
2552         * This will make sure that pinned stack always stays on top.
2553         * @param requestedPosition Position requested by caller.
2554         * @param stack Stack to be added or positioned.
2555         * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
2556         * @return The proper position for the stack.
2557         */
2558        private int findPositionForStack(int requestedPosition, TaskStack stack, boolean adding) {
2559            final int topChildPosition = mChildren.size() - 1;
2560            boolean toTop = requestedPosition == POSITION_TOP;
2561            toTop |= adding ? requestedPosition >= topChildPosition + 1
2562                    : requestedPosition >= topChildPosition;
2563            int targetPosition = requestedPosition;
2564
2565            if (toTop
2566                    && mService.isStackVisibleLocked(PINNED_STACK_ID)
2567                    && stack.mStackId != PINNED_STACK_ID) {
2568                // The pinned stack is always the top most stack (always-on-top) when it is visible.
2569                TaskStack topStack = mChildren.get(topChildPosition);
2570                if (topStack.mStackId != PINNED_STACK_ID) {
2571                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
2572                }
2573
2574                // So, stack is moved just below the pinned stack.
2575                // When we're adding a new stack the target is the current pinned stack position.
2576                // When we're positioning an existing stack the target is the position below pinned
2577                // stack, because WindowContainer#positionAt() first removes element and then adds it
2578                // to specified place.
2579                targetPosition = adding ? topChildPosition : topChildPosition - 1;
2580            }
2581
2582            return targetPosition;
2583        }
2584
2585        @Override
2586        boolean forAllWindows(ToBooleanFunction<WindowState> callback,
2587                boolean traverseTopToBottom) {
2588            if (traverseTopToBottom) {
2589                if (super.forAllWindows(callback, traverseTopToBottom)) {
2590                    return true;
2591                }
2592                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
2593                    return true;
2594                }
2595            } else {
2596                if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
2597                    return true;
2598                }
2599                if (super.forAllWindows(callback, traverseTopToBottom)) {
2600                    return true;
2601                }
2602            }
2603            return false;
2604        }
2605
2606        private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
2607                boolean traverseTopToBottom) {
2608            // For legacy reasons we process the TaskStack.mExitingAppTokens first here before the
2609            // app tokens.
2610            // TODO: Investigate if we need to continue to do this or if we can just process them
2611            // in-order.
2612            if (traverseTopToBottom) {
2613                for (int i = mChildren.size() - 1; i >= 0; --i) {
2614                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
2615                    for (int j = appTokens.size() - 1; j >= 0; --j) {
2616                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
2617                                traverseTopToBottom)) {
2618                            return true;
2619                        }
2620                    }
2621                }
2622            } else {
2623                final int count = mChildren.size();
2624                for (int i = 0; i < count; ++i) {
2625                    final AppTokenList appTokens = mChildren.get(i).mExitingAppTokens;
2626                    final int appTokensCount = appTokens.size();
2627                    for (int j = 0; j < appTokensCount; j++) {
2628                        if (appTokens.get(j).forAllWindowsUnchecked(callback,
2629                                traverseTopToBottom)) {
2630                            return true;
2631                        }
2632                    }
2633                }
2634            }
2635            return false;
2636        }
2637
2638        @Override
2639        int getOrientation() {
2640            if (mService.isStackVisibleLocked(DOCKED_STACK_ID)
2641                    || mService.isStackVisibleLocked(FREEFORM_WORKSPACE_STACK_ID)) {
2642                // Apps and their containers are not allowed to specify an orientation while the
2643                // docked or freeform stack is visible...except for the home stack/task if the
2644                // docked stack is minimized and it actually set something.
2645                if (mHomeStack != null && mHomeStack.isVisible()
2646                        && mDividerControllerLocked.isMinimizedDock()) {
2647                    final int orientation = mHomeStack.getOrientation();
2648                    if (orientation != SCREEN_ORIENTATION_UNSET) {
2649                        return orientation;
2650                    }
2651                }
2652                return SCREEN_ORIENTATION_UNSPECIFIED;
2653            }
2654
2655            final int orientation = super.getOrientation();
2656            if (orientation != SCREEN_ORIENTATION_UNSET
2657                    && orientation != SCREEN_ORIENTATION_BEHIND) {
2658                if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
2659                        "App is requesting an orientation, return " + orientation);
2660                return orientation;
2661            }
2662
2663            if (DEBUG_ORIENTATION) Slog.v(TAG_WM,
2664                    "No app is requesting an orientation, return " + mService.mLastOrientation);
2665            // The next app has not been requested to be visible, so we keep the current orientation
2666            // to prevent freezing/unfreezing the display too early.
2667            return mService.mLastOrientation;
2668        }
2669    }
2670
2671    /**
2672     * Window container class that contains all containers on this display that are not related to
2673     * Apps. E.g. status bar.
2674     */
2675    private final class NonAppWindowContainers extends DisplayChildWindowContainer<WindowToken> {
2676        /**
2677         * Compares two child window tokens returns -1 if the first is lesser than the second in
2678         * terms of z-order and 1 otherwise.
2679         */
2680        private final Comparator<WindowToken> mWindowComparator = (token1, token2) ->
2681                // Tokens with higher base layer are z-ordered on-top.
2682                mService.mPolicy.windowTypeToLayerLw(token1.windowType)
2683                < mService.mPolicy.windowTypeToLayerLw(token2.windowType) ? -1 : 1;
2684
2685        private final Predicate<WindowState> mGetOrientingWindow = w -> {
2686            if (!w.isVisibleLw() || !w.mPolicyVisibilityAfterAnim) {
2687                return false;
2688            }
2689            final int req = w.mAttrs.screenOrientation;
2690            if(req == SCREEN_ORIENTATION_UNSPECIFIED || req == SCREEN_ORIENTATION_BEHIND
2691                    || req == SCREEN_ORIENTATION_UNSET) {
2692                return false;
2693            }
2694            return true;
2695        };
2696
2697        private final String mName;
2698        NonAppWindowContainers(String name) {
2699            mName = name;
2700        }
2701
2702        void addChild(WindowToken token) {
2703            addChild(token, mWindowComparator);
2704        }
2705
2706        @Override
2707        int getOrientation() {
2708            final WindowManagerPolicy policy = mService.mPolicy;
2709            // Find a window requesting orientation.
2710            final WindowState win = getWindow(mGetOrientingWindow);
2711
2712            if (win != null) {
2713                final int req = win.mAttrs.screenOrientation;
2714                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
2715                if (policy.isKeyguardHostWindow(win.mAttrs)) {
2716                    mService.mLastKeyguardForcedOrientation = req;
2717                }
2718                return (mService.mLastWindowForcedOrientation = req);
2719            }
2720
2721            mService.mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
2722
2723            if (policy.isKeyguardShowingAndNotOccluded()) {
2724                return mService.mLastKeyguardForcedOrientation;
2725            }
2726
2727            return SCREEN_ORIENTATION_UNSET;
2728        }
2729
2730        @Override
2731        String getName() {
2732            return mName;
2733        }
2734    }
2735
2736    /**
2737     * Interface to screenshot into various types, i.e. {@link Bitmap} and {@link GraphicBuffer}.
2738     */
2739    @FunctionalInterface
2740    private interface Screenshoter<E> {
2741        E screenshot(Rect sourceCrop, int width, int height, int minLayer, int maxLayer,
2742                boolean useIdentityTransform, int rotation);
2743    }
2744}
2745