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