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