1/*
2 * Copyright (C) 2011 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 android.app.ActivityManager;
20import android.app.AppOpsManager;
21import android.content.Context;
22import android.content.res.Configuration;
23import android.graphics.Matrix;
24import android.graphics.PixelFormat;
25import android.graphics.Point;
26import android.graphics.Rect;
27import android.graphics.Region;
28import android.os.IBinder;
29import android.os.PowerManager;
30import android.os.RemoteCallbackList;
31import android.os.RemoteException;
32import android.os.SystemClock;
33import android.os.Trace;
34import android.os.UserHandle;
35import android.os.WorkSource;
36import android.util.DisplayMetrics;
37import android.util.Slog;
38import android.util.TimeUtils;
39import android.view.Display;
40import android.view.DisplayInfo;
41import android.view.Gravity;
42import android.view.IApplicationToken;
43import android.view.IWindow;
44import android.view.IWindowFocusObserver;
45import android.view.IWindowId;
46import android.view.InputChannel;
47import android.view.InputEvent;
48import android.view.InputEventReceiver;
49import android.view.View;
50import android.view.ViewTreeObserver;
51import android.view.WindowManager;
52import android.view.WindowManagerPolicy;
53
54import com.android.server.input.InputWindowHandle;
55
56import java.io.PrintWriter;
57import java.util.ArrayList;
58
59import static android.app.ActivityManager.StackId;
60import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
61import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
62import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
63import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT;
64import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
65import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION;
66import static android.view.ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE;
67import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
68import static android.view.WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
69import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
70import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
71import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
72import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
73import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
74import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
75import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
76import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
77import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
78import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
79import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
80import static android.view.WindowManager.LayoutParams.MATCH_PARENT;
81import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
82import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
83import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
84import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH;
85import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
86import static android.view.WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST;
87import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
88import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
89import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
90import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
91import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
92import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
93import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
94import static android.view.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
95import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_DOCKED_DIVIDER;
96import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
97import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
98import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
99import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
100import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_CONFIGURATION;
101import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
102import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT;
103import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
104import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_POWER;
105import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RESIZE;
106import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
107import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
108import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
109
110class WindowList extends ArrayList<WindowState> {
111    WindowList() {}
112    WindowList(WindowList windowList) {
113        super(windowList);
114    }
115}
116
117/**
118 * A window in the window manager.
119 */
120final class WindowState implements WindowManagerPolicy.WindowState {
121    static final String TAG = TAG_WITH_CLASS_NAME ? "WindowState" : TAG_WM;
122
123    // The minimal size of a window within the usable area of the freeform stack.
124    // TODO(multi-window): fix the min sizes when we have mininum width/height support,
125    //                     use hard-coded min sizes for now.
126    static final int MINIMUM_VISIBLE_WIDTH_IN_DP = 48;
127    static final int MINIMUM_VISIBLE_HEIGHT_IN_DP = 32;
128
129    // The thickness of a window resize handle outside the window bounds on the free form workspace
130    // to capture touch events in that area.
131    static final int RESIZE_HANDLE_WIDTH_IN_DP = 30;
132
133    static final boolean DEBUG_DISABLE_SAVING_SURFACES = false;
134
135    final WindowManagerService mService;
136    final WindowManagerPolicy mPolicy;
137    final Context mContext;
138    final Session mSession;
139    final IWindow mClient;
140    final int mAppOp;
141    // UserId and appId of the owner. Don't display windows of non-current user.
142    final int mOwnerUid;
143    final IWindowId mWindowId;
144    WindowToken mToken;
145    WindowToken mRootToken;
146    AppWindowToken mAppToken;
147    AppWindowToken mTargetAppToken;
148
149    // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
150    // modified they will need to be locked.
151    final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
152    final DeathRecipient mDeathRecipient;
153    final WindowState mAttachedWindow;
154    final WindowList mChildWindows = new WindowList();
155    final int mBaseLayer;
156    final int mSubLayer;
157    final boolean mLayoutAttached;
158    final boolean mIsImWindow;
159    final boolean mIsWallpaper;
160    final boolean mIsFloatingLayer;
161    int mSeq;
162    boolean mEnforceSizeCompat;
163    int mViewVisibility;
164    int mSystemUiVisibility;
165    boolean mPolicyVisibility = true;
166    boolean mPolicyVisibilityAfterAnim = true;
167    boolean mAppOpVisibility = true;
168    boolean mAppFreezing;
169    boolean mAttachedHidden;    // is our parent window hidden?
170    boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
171    boolean mDragResizing;
172    boolean mDragResizingChangeReported;
173    int mResizeMode;
174
175    RemoteCallbackList<IWindowFocusObserver> mFocusCallbacks;
176
177    /**
178     * The window size that was requested by the application.  These are in
179     * the application's coordinate space (without compatibility scale applied).
180     */
181    int mRequestedWidth;
182    int mRequestedHeight;
183    int mLastRequestedWidth;
184    int mLastRequestedHeight;
185
186    int mLayer;
187    boolean mHaveFrame;
188    boolean mObscured;
189    boolean mTurnOnScreen;
190
191    int mLayoutSeq = -1;
192
193    private final Configuration mTmpConfig = new Configuration();
194    // Represents the changes from our override configuration applied
195    // to the global configuration. This is the only form of configuration
196    // which is suitable for delivery to the client.
197    private Configuration mMergedConfiguration = new Configuration();
198    // Sticky answer to isConfigChanged(), remains true until new Configuration is assigned.
199    // Used only on {@link #TYPE_KEYGUARD}.
200    private boolean mConfigHasChanged;
201
202    /**
203     * Actual position of the surface shown on-screen (may be modified by animation). These are
204     * in the screen's coordinate space (WITH the compatibility scale applied).
205     */
206    final Point mShownPosition = new Point();
207
208    /**
209     * Insets that determine the actually visible area.  These are in the application's
210     * coordinate space (without compatibility scale applied).
211     */
212    final Rect mVisibleInsets = new Rect();
213    final Rect mLastVisibleInsets = new Rect();
214    boolean mVisibleInsetsChanged;
215
216    /**
217     * Insets that are covered by system windows (such as the status bar) and
218     * transient docking windows (such as the IME).  These are in the application's
219     * coordinate space (without compatibility scale applied).
220     */
221    final Rect mContentInsets = new Rect();
222    final Rect mLastContentInsets = new Rect();
223    boolean mContentInsetsChanged;
224
225    /**
226     * Insets that determine the area covered by the display overscan region.  These are in the
227     * application's coordinate space (without compatibility scale applied).
228     */
229    final Rect mOverscanInsets = new Rect();
230    final Rect mLastOverscanInsets = new Rect();
231    boolean mOverscanInsetsChanged;
232
233    /**
234     * Insets that determine the area covered by the stable system windows.  These are in the
235     * application's coordinate space (without compatibility scale applied).
236     */
237    final Rect mStableInsets = new Rect();
238    final Rect mLastStableInsets = new Rect();
239    boolean mStableInsetsChanged;
240
241    /**
242     * Outsets determine the area outside of the surface where we want to pretend that it's possible
243     * to draw anyway.
244     */
245    final Rect mOutsets = new Rect();
246    final Rect mLastOutsets = new Rect();
247    boolean mOutsetsChanged = false;
248
249    /**
250     * Set to true if we are waiting for this window to receive its
251     * given internal insets before laying out other windows based on it.
252     */
253    boolean mGivenInsetsPending;
254
255    /**
256     * These are the content insets that were given during layout for
257     * this window, to be applied to windows behind it.
258     */
259    final Rect mGivenContentInsets = new Rect();
260
261    /**
262     * These are the visible insets that were given during layout for
263     * this window, to be applied to windows behind it.
264     */
265    final Rect mGivenVisibleInsets = new Rect();
266
267    /**
268     * This is the given touchable area relative to the window frame, or null if none.
269     */
270    final Region mGivenTouchableRegion = new Region();
271
272    /**
273     * Flag indicating whether the touchable region should be adjusted by
274     * the visible insets; if false the area outside the visible insets is
275     * NOT touchable, so we must use those to adjust the frame during hit
276     * tests.
277     */
278    int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
279
280    // Current transformation being applied.
281    float mGlobalScale=1;
282    float mInvGlobalScale=1;
283    float mHScale=1, mVScale=1;
284    float mLastHScale=1, mLastVScale=1;
285    final Matrix mTmpMatrix = new Matrix();
286
287    // "Real" frame that the application sees, in display coordinate space.
288    final Rect mFrame = new Rect();
289    final Rect mLastFrame = new Rect();
290    // Frame that is scaled to the application's coordinate space when in
291    // screen size compatibility mode.
292    final Rect mCompatFrame = new Rect();
293
294    final Rect mContainingFrame = new Rect();
295
296    final Rect mParentFrame = new Rect();
297
298    // The entire screen area of the {@link TaskStack} this window is in. Usually equal to the
299    // screen area of the device.
300    final Rect mDisplayFrame = new Rect();
301
302    // The region of the display frame that the display type supports displaying content on. This
303    // is mostly a special case for TV where some displays don’t have the entire display usable.
304    // {@link WindowManager.LayoutParams#FLAG_LAYOUT_IN_OVERSCAN} flag can be used to allow
305    // window display contents to extend into the overscan region.
306    final Rect mOverscanFrame = new Rect();
307
308    // The display frame minus the stable insets. This value is always constant regardless of if
309    // the status bar or navigation bar is visible.
310    final Rect mStableFrame = new Rect();
311
312    // The area not occupied by the status and navigation bars. So, if both status and navigation
313    // bars are visible, the decor frame is equal to the stable frame.
314    final Rect mDecorFrame = new Rect();
315
316    // Equal to the decor frame if the IME (e.g. keyboard) is not present. Equal to the decor frame
317    // minus the area occupied by the IME if the IME is present.
318    final Rect mContentFrame = new Rect();
319
320    // Legacy stuff. Generally equal to the content frame expect when the IME for older apps
321    // displays hint text.
322    final Rect mVisibleFrame = new Rect();
323
324    // Frame that includes dead area outside of the surface but where we want to pretend that it's
325    // possible to draw.
326    final Rect mOutsetFrame = new Rect();
327
328    /**
329     * Usually empty. Set to the task's tempInsetFrame. See
330     *{@link android.app.IActivityManager#resizeDockedStack}.
331     */
332    final Rect mInsetFrame = new Rect();
333
334    private static final Rect sTmpRect = new Rect();
335
336    boolean mContentChanged;
337
338    // If a window showing a wallpaper: the requested offset for the
339    // wallpaper; if a wallpaper window: the currently applied offset.
340    float mWallpaperX = -1;
341    float mWallpaperY = -1;
342
343    // If a window showing a wallpaper: what fraction of the offset
344    // range corresponds to a full virtual screen.
345    float mWallpaperXStep = -1;
346    float mWallpaperYStep = -1;
347
348    // If a window showing a wallpaper: a raw pixel offset to forcibly apply
349    // to its window; if a wallpaper window: not used.
350    int mWallpaperDisplayOffsetX = Integer.MIN_VALUE;
351    int mWallpaperDisplayOffsetY = Integer.MIN_VALUE;
352
353    // Wallpaper windows: pixels offset based on above variables.
354    int mXOffset;
355    int mYOffset;
356
357    /**
358     * This is set after IWindowSession.relayout() has been called at
359     * least once for the window.  It allows us to detect the situation
360     * where we don't yet have a surface, but should have one soon, so
361     * we can give the window focus before waiting for the relayout.
362     */
363    boolean mRelayoutCalled;
364
365    boolean mInRelayout;
366
367    /**
368     * If the application has called relayout() with changes that can
369     * impact its window's size, we need to perform a layout pass on it
370     * even if it is not currently visible for layout.  This is set
371     * when in that case until the layout is done.
372     */
373    boolean mLayoutNeeded;
374
375    /** Currently running an exit animation? */
376    boolean mAnimatingExit;
377
378    /** Currently on the mDestroySurface list? */
379    boolean mDestroying;
380
381    /** Completely remove from window manager after exit animation? */
382    boolean mRemoveOnExit;
383
384    /**
385     * Whether the app died while it was visible, if true we might need
386     * to continue to show it until it's restarted.
387     */
388    boolean mAppDied;
389
390    /**
391     * Set when the orientation is changing and this window has not yet
392     * been updated for the new orientation.
393     */
394    boolean mOrientationChanging;
395
396    /**
397     * How long we last kept the screen frozen.
398     */
399    int mLastFreezeDuration;
400
401    /** Is this window now (or just being) removed? */
402    boolean mRemoved;
403
404    /**
405     * It is save to remove the window and destroy the surface because the client requested removal
406     * or some other higher level component said so (e.g. activity manager).
407     * TODO: We should either have different booleans for the removal reason or use a bit-field.
408     */
409    boolean mWindowRemovalAllowed;
410
411    /**
412     * Temp for keeping track of windows that have been removed when
413     * rebuilding window list.
414     */
415    boolean mRebuilding;
416
417    // Input channel and input window handle used by the input dispatcher.
418    final InputWindowHandle mInputWindowHandle;
419    InputChannel mInputChannel;
420    InputChannel mClientChannel;
421
422    // Used to improve performance of toString()
423    String mStringNameCache;
424    CharSequence mLastTitle;
425    boolean mWasExiting;
426
427    final WindowStateAnimator mWinAnimator;
428
429    boolean mHasSurface = false;
430
431    boolean mNotOnAppsDisplay = false;
432    DisplayContent  mDisplayContent;
433
434    /** When true this window can be displayed on screens owther than mOwnerUid's */
435    private boolean mShowToOwnerOnly;
436
437    // Whether the window has a saved surface from last pause, which can be
438    // used to start an entering animation earlier.
439    private boolean mSurfaceSaved = false;
440
441    // Whether we're performing an entering animation with a saved surface. This flag is
442    // true during the time we're showing a window with a previously saved surface. It's
443    // cleared when surface is destroyed, saved, or re-drawn by the app.
444    private boolean mAnimatingWithSavedSurface;
445
446    // Whether the window was visible when we set the app to invisible last time. WM uses
447    // this as a hint to restore the surface (if available) for early animation next time
448    // the app is brought visible.
449    boolean mWasVisibleBeforeClientHidden;
450
451    // This window will be replaced due to relaunch. This allows window manager
452    // to differentiate between simple removal of a window and replacement. In the latter case it
453    // will preserve the old window until the new one is drawn.
454    boolean mWillReplaceWindow = false;
455    // If true, the replaced window was already requested to be removed.
456    boolean mReplacingRemoveRequested = false;
457    // Whether the replacement of the window should trigger app transition animation.
458    boolean mAnimateReplacingWindow = false;
459    // If not null, the window that will be used to replace the old one. This is being set when
460    // the window is added and unset when this window reports its first draw.
461    WindowState mReplacingWindow = null;
462    // For the new window in the replacement transition, if we have
463    // requested to replace without animation, then we should
464    // make sure we also don't apply an enter animation for
465    // the new window.
466    boolean mSkipEnterAnimationForSeamlessReplacement = false;
467    // Whether this window is being moved via the resize API
468    boolean mMovedByResize;
469
470    /**
471     * Wake lock for drawing.
472     * Even though it's slightly more expensive to do so, we will use a separate wake lock
473     * for each app that is requesting to draw while dozing so that we can accurately track
474     * who is preventing the system from suspending.
475     * This lock is only acquired on first use.
476     */
477    PowerManager.WakeLock mDrawLock;
478
479    final private Rect mTmpRect = new Rect();
480
481    /**
482     * See {@link #notifyMovedInStack}.
483     */
484    private boolean mJustMovedInStack;
485
486    /**
487     * Whether the window was resized by us while it was gone for layout.
488     */
489    boolean mResizedWhileGone = false;
490
491    /** @see #isResizedWhileNotDragResizing(). */
492    private boolean mResizedWhileNotDragResizing;
493
494    /** @see #isResizedWhileNotDragResizingReported(). */
495    private boolean mResizedWhileNotDragResizingReported;
496
497    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
498           WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
499           int viewVisibility, final DisplayContent displayContent) {
500        mService = service;
501        mSession = s;
502        mClient = c;
503        mAppOp = appOp;
504        mToken = token;
505        mOwnerUid = s.mUid;
506        mWindowId = new IWindowId.Stub() {
507            @Override
508            public void registerFocusObserver(IWindowFocusObserver observer) {
509                WindowState.this.registerFocusObserver(observer);
510            }
511            @Override
512            public void unregisterFocusObserver(IWindowFocusObserver observer) {
513                WindowState.this.unregisterFocusObserver(observer);
514            }
515            @Override
516            public boolean isFocused() {
517                return WindowState.this.isFocused();
518            }
519        };
520        mAttrs.copyFrom(a);
521        mViewVisibility = viewVisibility;
522        mDisplayContent = displayContent;
523        mPolicy = mService.mPolicy;
524        mContext = mService.mContext;
525        DeathRecipient deathRecipient = new DeathRecipient();
526        mSeq = seq;
527        mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
528        if (WindowManagerService.localLOGV) Slog.v(
529            TAG, "Window " + this + " client=" + c.asBinder()
530            + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
531        try {
532            c.asBinder().linkToDeath(deathRecipient, 0);
533        } catch (RemoteException e) {
534            mDeathRecipient = null;
535            mAttachedWindow = null;
536            mLayoutAttached = false;
537            mIsImWindow = false;
538            mIsWallpaper = false;
539            mIsFloatingLayer = false;
540            mBaseLayer = 0;
541            mSubLayer = 0;
542            mInputWindowHandle = null;
543            mWinAnimator = null;
544            return;
545        }
546        mDeathRecipient = deathRecipient;
547
548        if ((mAttrs.type >= FIRST_SUB_WINDOW &&
549                mAttrs.type <= LAST_SUB_WINDOW)) {
550            // The multiplier here is to reserve space for multiple
551            // windows in the same type layer.
552            mBaseLayer = mPolicy.windowTypeToLayerLw(
553                    attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
554                    + WindowManagerService.TYPE_LAYER_OFFSET;
555            mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
556            mAttachedWindow = attachedWindow;
557            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
558
559            final WindowList childWindows = mAttachedWindow.mChildWindows;
560            final int numChildWindows = childWindows.size();
561            if (numChildWindows == 0) {
562                childWindows.add(this);
563            } else {
564                boolean added = false;
565                for (int i = 0; i < numChildWindows; i++) {
566                    final int childSubLayer = childWindows.get(i).mSubLayer;
567                    if (mSubLayer < childSubLayer
568                            || (mSubLayer == childSubLayer && childSubLayer < 0)) {
569                        // We insert the child window into the list ordered by the sub-layer. For
570                        // same sub-layers, the negative one should go below others; the positive
571                        // one should go above others.
572                        childWindows.add(i, this);
573                        added = true;
574                        break;
575                    }
576                }
577                if (!added) {
578                    childWindows.add(this);
579                }
580            }
581
582            mLayoutAttached = mAttrs.type !=
583                    WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
584            mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
585                    || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
586            mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
587            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
588        } else {
589            // The multiplier here is to reserve space for multiple
590            // windows in the same type layer.
591            mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
592                    * WindowManagerService.TYPE_LAYER_MULTIPLIER
593                    + WindowManagerService.TYPE_LAYER_OFFSET;
594            mSubLayer = 0;
595            mAttachedWindow = null;
596            mLayoutAttached = false;
597            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
598                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
599            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
600            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
601        }
602
603        WindowState appWin = this;
604        while (appWin.isChildWindow()) {
605            appWin = appWin.mAttachedWindow;
606        }
607        WindowToken appToken = appWin.mToken;
608        while (appToken.appWindowToken == null) {
609            WindowToken parent = mService.mTokenMap.get(appToken.token);
610            if (parent == null || appToken == parent) {
611                break;
612            }
613            appToken = parent;
614        }
615        mRootToken = appToken;
616        mAppToken = appToken.appWindowToken;
617        if (mAppToken != null) {
618            final DisplayContent appDisplay = getDisplayContent();
619            mNotOnAppsDisplay = displayContent != appDisplay;
620
621            if (mAppToken.showForAllUsers) {
622                // Windows for apps that can show for all users should also show when the
623                // device is locked.
624                mAttrs.flags |= FLAG_SHOW_WHEN_LOCKED;
625            }
626        }
627
628        mWinAnimator = new WindowStateAnimator(this);
629        mWinAnimator.mAlpha = a.alpha;
630
631        mRequestedWidth = 0;
632        mRequestedHeight = 0;
633        mLastRequestedWidth = 0;
634        mLastRequestedHeight = 0;
635        mXOffset = 0;
636        mYOffset = 0;
637        mLayer = 0;
638        mInputWindowHandle = new InputWindowHandle(
639                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
640                displayContent.getDisplayId());
641    }
642
643    void attach() {
644        if (WindowManagerService.localLOGV) Slog.v(
645            TAG, "Attaching " + this + " token=" + mToken
646            + ", list=" + mToken.windows);
647        mSession.windowAddedLocked();
648    }
649
650    @Override
651    public int getOwningUid() {
652        return mOwnerUid;
653    }
654
655    @Override
656    public String getOwningPackage() {
657        return mAttrs.packageName;
658    }
659
660    /**
661     * Subtracts the insets calculated by intersecting {@param layoutFrame} with {@param insetFrame}
662     * from {@param frame}. In other words, it applies the insets that would result if
663     * {@param frame} would be shifted to {@param layoutFrame} and then applying the insets from
664     * {@param insetFrame}. Also it respects {@param displayFrame} in case window has minimum
665     * width/height applied and insets should be overridden.
666     */
667    private void subtractInsets(Rect frame, Rect layoutFrame, Rect insetFrame, Rect displayFrame) {
668        final int left = Math.max(0, insetFrame.left - Math.max(layoutFrame.left, displayFrame.left));
669        final int top = Math.max(0, insetFrame.top - Math.max(layoutFrame.top, displayFrame.top));
670        final int right = Math.max(0, Math.min(layoutFrame.right, displayFrame.right) - insetFrame.right);
671        final int bottom = Math.max(0, Math.min(layoutFrame.bottom, displayFrame.bottom) - insetFrame.bottom);
672        frame.inset(left, top, right, bottom);
673    }
674
675    @Override
676    public void computeFrameLw(Rect pf, Rect df, Rect of, Rect cf, Rect vf, Rect dcf, Rect sf,
677            Rect osf) {
678        if (mWillReplaceWindow && (mAnimatingExit || !mReplacingRemoveRequested)) {
679            // This window is being replaced and either already got information that it's being
680            // removed or we are still waiting for some information. Because of this we don't
681            // want to apply any more changes to it, so it remains in this state until new window
682            // appears.
683            return;
684        }
685        mHaveFrame = true;
686
687        final Task task = getTask();
688        final boolean fullscreenTask = !isInMultiWindowMode();
689        final boolean windowsAreFloating = task != null && task.isFloating();
690
691        // If the task has temp inset bounds set, we have to make sure all its windows uses
692        // the temp inset frame. Otherwise different display frames get applied to the main
693        // window and the child window, making them misaligned.
694        if (fullscreenTask) {
695            mInsetFrame.setEmpty();
696        } else {
697            task.getTempInsetBounds(mInsetFrame);
698        }
699
700        // Denotes the actual frame used to calculate the insets and to perform the layout. When
701        // resizing in docked mode, we'd like to freeze the layout, so we also need to freeze the
702        // insets temporarily. By the notion of a task having a different layout frame, we can
703        // achieve that while still moving the task around.
704        final Rect layoutContainingFrame;
705        final Rect layoutDisplayFrame;
706
707        // The offset from the layout containing frame to the actual containing frame.
708        final int layoutXDiff;
709        final int layoutYDiff;
710        if (fullscreenTask || layoutInParentFrame()) {
711            // We use the parent frame as the containing frame for fullscreen and child windows
712            mContainingFrame.set(pf);
713            mDisplayFrame.set(df);
714            layoutDisplayFrame = df;
715            layoutContainingFrame = pf;
716            layoutXDiff = 0;
717            layoutYDiff = 0;
718        } else {
719            task.getBounds(mContainingFrame);
720            if (mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) {
721
722                // If the bounds are frozen, we still want to translate the window freely and only
723                // freeze the size.
724                Rect frozen = mAppToken.mFrozenBounds.peek();
725                mContainingFrame.right = mContainingFrame.left + frozen.width();
726                mContainingFrame.bottom = mContainingFrame.top + frozen.height();
727            }
728            final WindowState imeWin = mService.mInputMethodWindow;
729            // IME is up and obscuring this window. Adjust the window position so it is visible.
730            if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
731                    if (windowsAreFloating && mContainingFrame.bottom > cf.bottom) {
732                        // In freeform we want to move the top up directly.
733                        // TODO: Investigate why this is cf not pf.
734                        mContainingFrame.top -= mContainingFrame.bottom - cf.bottom;
735                    } else if (mContainingFrame.bottom > pf.bottom) {
736                        // But in docked we want to behave like fullscreen
737                        // and behave as if the task were given smaller bounds
738                        // for the purposes of layout.
739                        mContainingFrame.bottom = pf.bottom;
740                    }
741            }
742
743            if (windowsAreFloating) {
744                // In floating modes (e.g. freeform, pinned) we have only to set the rectangle
745                // if it wasn't set already. No need to intersect it with the (visible)
746                // "content frame" since it is allowed to be outside the visible desktop.
747                if (mContainingFrame.isEmpty()) {
748                    mContainingFrame.set(cf);
749                }
750            }
751            mDisplayFrame.set(mContainingFrame);
752            layoutXDiff = !mInsetFrame.isEmpty() ? mInsetFrame.left - mContainingFrame.left : 0;
753            layoutYDiff = !mInsetFrame.isEmpty() ? mInsetFrame.top - mContainingFrame.top : 0;
754            layoutContainingFrame = !mInsetFrame.isEmpty() ? mInsetFrame : mContainingFrame;
755            mTmpRect.set(0, 0, mDisplayContent.getDisplayInfo().logicalWidth,
756                    mDisplayContent.getDisplayInfo().logicalHeight);
757            subtractInsets(mDisplayFrame, layoutContainingFrame, df, mTmpRect);
758            if (!layoutInParentFrame()) {
759                subtractInsets(mContainingFrame, layoutContainingFrame, pf, mTmpRect);
760                subtractInsets(mInsetFrame, layoutContainingFrame, pf, mTmpRect);
761            }
762            layoutDisplayFrame = df;
763            layoutDisplayFrame.intersect(layoutContainingFrame);
764        }
765
766        final int pw = mContainingFrame.width();
767        final int ph = mContainingFrame.height();
768
769        if (!mParentFrame.equals(pf)) {
770            //Slog.i(TAG_WM, "Window " + this + " content frame from " + mParentFrame
771            //        + " to " + pf);
772            mParentFrame.set(pf);
773            mContentChanged = true;
774        }
775        if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
776            mLastRequestedWidth = mRequestedWidth;
777            mLastRequestedHeight = mRequestedHeight;
778            mContentChanged = true;
779        }
780
781        mOverscanFrame.set(of);
782        mContentFrame.set(cf);
783        mVisibleFrame.set(vf);
784        mDecorFrame.set(dcf);
785        mStableFrame.set(sf);
786        final boolean hasOutsets = osf != null;
787        if (hasOutsets) {
788            mOutsetFrame.set(osf);
789        }
790
791        final int fw = mFrame.width();
792        final int fh = mFrame.height();
793
794        applyGravityAndUpdateFrame(layoutContainingFrame, layoutDisplayFrame);
795
796        // Calculate the outsets before the content frame gets shrinked to the window frame.
797        if (hasOutsets) {
798            mOutsets.set(Math.max(mContentFrame.left - mOutsetFrame.left, 0),
799                    Math.max(mContentFrame.top - mOutsetFrame.top, 0),
800                    Math.max(mOutsetFrame.right - mContentFrame.right, 0),
801                    Math.max(mOutsetFrame.bottom - mContentFrame.bottom, 0));
802        } else {
803            mOutsets.set(0, 0, 0, 0);
804        }
805
806        // Make sure the content and visible frames are inside of the
807        // final window frame.
808        if (windowsAreFloating && !mFrame.isEmpty()) {
809            // Keep the frame out of the blocked system area, limit it in size to the content area
810            // and make sure that there is always a minimum visible so that the user can drag it
811            // into a usable area..
812            final int height = Math.min(mFrame.height(), mContentFrame.height());
813            final int width = Math.min(mContentFrame.width(), mFrame.width());
814            final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
815            final int minVisibleHeight = WindowManagerService.dipToPixel(
816                    MINIMUM_VISIBLE_HEIGHT_IN_DP, displayMetrics);
817            final int minVisibleWidth = WindowManagerService.dipToPixel(
818                    MINIMUM_VISIBLE_WIDTH_IN_DP, displayMetrics);
819            final int top = Math.max(mContentFrame.top,
820                    Math.min(mFrame.top, mContentFrame.bottom - minVisibleHeight));
821            final int left = Math.max(mContentFrame.left + minVisibleWidth - width,
822                    Math.min(mFrame.left, mContentFrame.right - minVisibleWidth));
823            mFrame.set(left, top, left + width, top + height);
824            mContentFrame.set(mFrame);
825            mVisibleFrame.set(mContentFrame);
826            mStableFrame.set(mContentFrame);
827        } else if (mAttrs.type == TYPE_DOCK_DIVIDER) {
828            mDisplayContent.getDockedDividerController().positionDockedStackedDivider(mFrame);
829            mContentFrame.set(mFrame);
830            if (!mFrame.equals(mLastFrame)) {
831                mMovedByResize = true;
832            }
833        } else {
834            mContentFrame.set(Math.max(mContentFrame.left, mFrame.left),
835                    Math.max(mContentFrame.top, mFrame.top),
836                    Math.min(mContentFrame.right, mFrame.right),
837                    Math.min(mContentFrame.bottom, mFrame.bottom));
838
839            mVisibleFrame.set(Math.max(mVisibleFrame.left, mFrame.left),
840                    Math.max(mVisibleFrame.top, mFrame.top),
841                    Math.min(mVisibleFrame.right, mFrame.right),
842                    Math.min(mVisibleFrame.bottom, mFrame.bottom));
843
844            mStableFrame.set(Math.max(mStableFrame.left, mFrame.left),
845                    Math.max(mStableFrame.top, mFrame.top),
846                    Math.min(mStableFrame.right, mFrame.right),
847                    Math.min(mStableFrame.bottom, mFrame.bottom));
848        }
849
850        if (fullscreenTask && !windowsAreFloating) {
851            // Windows that are not fullscreen can be positioned outside of the display frame,
852            // but that is not a reason to provide them with overscan insets.
853            mOverscanInsets.set(Math.max(mOverscanFrame.left - layoutContainingFrame.left, 0),
854                    Math.max(mOverscanFrame.top - layoutContainingFrame.top, 0),
855                    Math.max(layoutContainingFrame.right - mOverscanFrame.right, 0),
856                    Math.max(layoutContainingFrame.bottom - mOverscanFrame.bottom, 0));
857        }
858
859        if (mAttrs.type == TYPE_DOCK_DIVIDER) {
860            // For the docked divider, we calculate the stable insets like a full-screen window
861            // so it can use it to calculate the snap positions.
862            mStableInsets.set(Math.max(mStableFrame.left - mDisplayFrame.left, 0),
863                    Math.max(mStableFrame.top - mDisplayFrame.top, 0),
864                    Math.max(mDisplayFrame.right - mStableFrame.right, 0),
865                    Math.max(mDisplayFrame.bottom - mStableFrame.bottom, 0));
866
867            // The divider doesn't care about insets in any case, so set it to empty so we don't
868            // trigger a relayout when moving it.
869            mContentInsets.setEmpty();
870            mVisibleInsets.setEmpty();
871        } else {
872            getDisplayContent().getLogicalDisplayRect(mTmpRect);
873            // Override right and/or bottom insets in case if the frame doesn't fit the screen in
874            // non-fullscreen mode.
875            boolean overrideRightInset = !fullscreenTask && mFrame.right > mTmpRect.right;
876            boolean overrideBottomInset = !fullscreenTask && mFrame.bottom > mTmpRect.bottom;
877            mContentInsets.set(mContentFrame.left - mFrame.left,
878                    mContentFrame.top - mFrame.top,
879                    overrideRightInset ? mTmpRect.right - mContentFrame.right
880                            : mFrame.right - mContentFrame.right,
881                    overrideBottomInset ? mTmpRect.bottom - mContentFrame.bottom
882                            : mFrame.bottom - mContentFrame.bottom);
883
884            mVisibleInsets.set(mVisibleFrame.left - mFrame.left,
885                    mVisibleFrame.top - mFrame.top,
886                    overrideRightInset ? mTmpRect.right - mVisibleFrame.right
887                            : mFrame.right - mVisibleFrame.right,
888                    overrideBottomInset ? mTmpRect.bottom - mVisibleFrame.bottom
889                            : mFrame.bottom - mVisibleFrame.bottom);
890
891            mStableInsets.set(Math.max(mStableFrame.left - mFrame.left, 0),
892                    Math.max(mStableFrame.top - mFrame.top, 0),
893                    overrideRightInset ? Math.max(mTmpRect.right - mStableFrame.right, 0)
894                            : Math.max(mFrame.right - mStableFrame.right, 0),
895                    overrideBottomInset ? Math.max(mTmpRect.bottom - mStableFrame.bottom, 0)
896                            :  Math.max(mFrame.bottom - mStableFrame.bottom, 0));
897        }
898
899        // Offset the actual frame by the amount layout frame is off.
900        mFrame.offset(-layoutXDiff, -layoutYDiff);
901        mCompatFrame.offset(-layoutXDiff, -layoutYDiff);
902        mContentFrame.offset(-layoutXDiff, -layoutYDiff);
903        mVisibleFrame.offset(-layoutXDiff, -layoutYDiff);
904        mStableFrame.offset(-layoutXDiff, -layoutYDiff);
905
906        mCompatFrame.set(mFrame);
907        if (mEnforceSizeCompat) {
908            // If there is a size compatibility scale being applied to the
909            // window, we need to apply this to its insets so that they are
910            // reported to the app in its coordinate space.
911            mOverscanInsets.scale(mInvGlobalScale);
912            mContentInsets.scale(mInvGlobalScale);
913            mVisibleInsets.scale(mInvGlobalScale);
914            mStableInsets.scale(mInvGlobalScale);
915            mOutsets.scale(mInvGlobalScale);
916
917            // Also the scaled frame that we report to the app needs to be
918            // adjusted to be in its coordinate space.
919            mCompatFrame.scale(mInvGlobalScale);
920        }
921
922        if (mIsWallpaper && (fw != mFrame.width() || fh != mFrame.height())) {
923            final DisplayContent displayContent = getDisplayContent();
924            if (displayContent != null) {
925                final DisplayInfo displayInfo = displayContent.getDisplayInfo();
926                mService.mWallpaperControllerLocked.updateWallpaperOffset(
927                        this, displayInfo.logicalWidth, displayInfo.logicalHeight, false);
928            }
929        }
930
931        if (DEBUG_LAYOUT || WindowManagerService.localLOGV) Slog.v(TAG,
932                "Resolving (mRequestedWidth="
933                + mRequestedWidth + ", mRequestedheight="
934                + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
935                + "): frame=" + mFrame.toShortString()
936                + " ci=" + mContentInsets.toShortString()
937                + " vi=" + mVisibleInsets.toShortString()
938                + " si=" + mStableInsets.toShortString()
939                + " of=" + mOutsets.toShortString());
940    }
941
942    @Override
943    public Rect getFrameLw() {
944        return mFrame;
945    }
946
947    @Override
948    public Point getShownPositionLw() {
949        return mShownPosition;
950    }
951
952    @Override
953    public Rect getDisplayFrameLw() {
954        return mDisplayFrame;
955    }
956
957    @Override
958    public Rect getOverscanFrameLw() {
959        return mOverscanFrame;
960    }
961
962    @Override
963    public Rect getContentFrameLw() {
964        return mContentFrame;
965    }
966
967    @Override
968    public Rect getVisibleFrameLw() {
969        return mVisibleFrame;
970    }
971
972    @Override
973    public boolean getGivenInsetsPendingLw() {
974        return mGivenInsetsPending;
975    }
976
977    @Override
978    public Rect getGivenContentInsetsLw() {
979        return mGivenContentInsets;
980    }
981
982    @Override
983    public Rect getGivenVisibleInsetsLw() {
984        return mGivenVisibleInsets;
985    }
986
987    @Override
988    public WindowManager.LayoutParams getAttrs() {
989        return mAttrs;
990    }
991
992    @Override
993    public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
994        int index = -1;
995        WindowState ws = this;
996        WindowList windows = getWindowList();
997        while (true) {
998            if (ws.mAttrs.needsMenuKey != WindowManager.LayoutParams.NEEDS_MENU_UNSET) {
999                return ws.mAttrs.needsMenuKey == WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE;
1000            }
1001            // If we reached the bottom of the range of windows we are considering,
1002            // assume no menu is needed.
1003            if (ws == bottom) {
1004                return false;
1005            }
1006            // The current window hasn't specified whether menu key is needed;
1007            // look behind it.
1008            // First, we may need to determine the starting position.
1009            if (index < 0) {
1010                index = windows.indexOf(ws);
1011            }
1012            index--;
1013            if (index < 0) {
1014                return false;
1015            }
1016            ws = windows.get(index);
1017        }
1018    }
1019
1020    @Override
1021    public int getSystemUiVisibility() {
1022        return mSystemUiVisibility;
1023    }
1024
1025    @Override
1026    public int getSurfaceLayer() {
1027        return mLayer;
1028    }
1029
1030    @Override
1031    public int getBaseType() {
1032        WindowState win = this;
1033        while (win.isChildWindow()) {
1034            win = win.mAttachedWindow;
1035        }
1036        return win.mAttrs.type;
1037    }
1038
1039    @Override
1040    public IApplicationToken getAppToken() {
1041        return mAppToken != null ? mAppToken.appToken : null;
1042    }
1043
1044    @Override
1045    public boolean isVoiceInteraction() {
1046        return mAppToken != null && mAppToken.voiceInteraction;
1047    }
1048
1049    boolean setInsetsChanged() {
1050        mOverscanInsetsChanged |= !mLastOverscanInsets.equals(mOverscanInsets);
1051        mContentInsetsChanged |= !mLastContentInsets.equals(mContentInsets);
1052        mVisibleInsetsChanged |= !mLastVisibleInsets.equals(mVisibleInsets);
1053        mStableInsetsChanged |= !mLastStableInsets.equals(mStableInsets);
1054        mOutsetsChanged |= !mLastOutsets.equals(mOutsets);
1055        return mOverscanInsetsChanged || mContentInsetsChanged || mVisibleInsetsChanged
1056                || mOutsetsChanged;
1057    }
1058
1059    public DisplayContent getDisplayContent() {
1060        if (mAppToken == null || mNotOnAppsDisplay) {
1061            return mDisplayContent;
1062        }
1063        final TaskStack stack = getStack();
1064        return stack == null ? mDisplayContent : stack.getDisplayContent();
1065    }
1066
1067    public DisplayInfo getDisplayInfo() {
1068        final DisplayContent displayContent = getDisplayContent();
1069        return displayContent != null ? displayContent.getDisplayInfo() : null;
1070    }
1071
1072    public int getDisplayId() {
1073        final DisplayContent displayContent = getDisplayContent();
1074        if (displayContent == null) {
1075            return -1;
1076        }
1077        return displayContent.getDisplayId();
1078    }
1079
1080    Task getTask() {
1081        return mAppToken != null ? mAppToken.mTask : null;
1082    }
1083
1084    TaskStack getStack() {
1085        Task task = getTask();
1086        if (task != null) {
1087            if (task.mStack != null) {
1088                return task.mStack;
1089            }
1090        }
1091        // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
1092        // associate them with some stack to enable dimming.
1093        return mAttrs.type >= WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
1094                && mDisplayContent != null ? mDisplayContent.getHomeStack() : null;
1095    }
1096
1097    /**
1098     * Retrieves the visible bounds of the window.
1099     * @param bounds The rect which gets the bounds.
1100     */
1101    void getVisibleBounds(Rect bounds) {
1102        final Task task = getTask();
1103        boolean intersectWithStackBounds = task != null && task.cropWindowsToStackBounds();
1104        bounds.setEmpty();
1105        mTmpRect.setEmpty();
1106        if (intersectWithStackBounds) {
1107            final TaskStack stack = task.mStack;
1108            if (stack != null) {
1109                stack.getDimBounds(mTmpRect);
1110            } else {
1111                intersectWithStackBounds = false;
1112            }
1113        }
1114
1115        bounds.set(mVisibleFrame);
1116        if (intersectWithStackBounds) {
1117            bounds.intersect(mTmpRect);
1118        }
1119
1120        if (bounds.isEmpty()) {
1121            bounds.set(mFrame);
1122            if (intersectWithStackBounds) {
1123                bounds.intersect(mTmpRect);
1124            }
1125            return;
1126        }
1127    }
1128
1129    public long getInputDispatchingTimeoutNanos() {
1130        return mAppToken != null
1131                ? mAppToken.inputDispatchingTimeoutNanos
1132                : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
1133    }
1134
1135    @Override
1136    public boolean hasAppShownWindows() {
1137        return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
1138    }
1139
1140    boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
1141        if (dsdx < .99999f || dsdx > 1.00001f) return false;
1142        if (dtdy < .99999f || dtdy > 1.00001f) return false;
1143        if (dtdx < -.000001f || dtdx > .000001f) return false;
1144        if (dsdy < -.000001f || dsdy > .000001f) return false;
1145        return true;
1146    }
1147
1148    void prelayout() {
1149        if (mEnforceSizeCompat) {
1150            mGlobalScale = mService.mCompatibleScreenScale;
1151            mInvGlobalScale = 1/mGlobalScale;
1152        } else {
1153            mGlobalScale = mInvGlobalScale = 1;
1154        }
1155    }
1156
1157    /**
1158     * Does the minimal check for visibility. Callers generally want to use one of the public
1159     * methods as they perform additional checks on the app token.
1160     * TODO: See if there are other places we can use this check below instead of duplicating...
1161     */
1162    private boolean isVisibleUnchecked() {
1163        return mHasSurface && mPolicyVisibility && !mAttachedHidden
1164                && !mAnimatingExit && !mDestroying && (!mIsWallpaper || mWallpaperVisible);
1165    }
1166
1167    /**
1168     * Is this window visible?  It is not visible if there is no surface, or we are in the process
1169     * of running an exit animation that will remove the surface, or its app token has been hidden.
1170     */
1171    @Override
1172    public boolean isVisibleLw() {
1173        return (mAppToken == null || !mAppToken.hiddenRequested) && isVisibleUnchecked();
1174    }
1175
1176    /**
1177     * Like {@link #isVisibleLw}, but also counts a window that is currently "hidden" behind the
1178     * keyguard as visible.  This allows us to apply things like window flags that impact the
1179     * keyguard. XXX I am starting to think we need to have ANOTHER visibility flag for this
1180     * "hidden behind keyguard" state rather than overloading mPolicyVisibility.  Ungh.
1181     */
1182    @Override
1183    public boolean isVisibleOrBehindKeyguardLw() {
1184        if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
1185            return false;
1186        }
1187        final AppWindowToken atoken = mAppToken;
1188        final boolean animating = atoken != null && atoken.mAppAnimator.animation != null;
1189        return mHasSurface && !mDestroying && !mAnimatingExit
1190                && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
1191                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden)
1192                        || mWinAnimator.mAnimation != null || animating);
1193    }
1194
1195    /**
1196     * Is this window visible, ignoring its app token? It is not visible if there is no surface,
1197     * or we are in the process of running an exit animation that will remove the surface.
1198     */
1199    public boolean isWinVisibleLw() {
1200        return (mAppToken == null || !mAppToken.hiddenRequested || mAppToken.mAppAnimator.animating)
1201                && isVisibleUnchecked();
1202    }
1203
1204    /**
1205     * The same as isVisible(), but follows the current hidden state of the associated app token,
1206     * not the pending requested hidden state.
1207     */
1208    boolean isVisibleNow() {
1209        return (!mRootToken.hidden || mAttrs.type == TYPE_APPLICATION_STARTING)
1210                && isVisibleUnchecked();
1211    }
1212
1213    /**
1214     * Can this window possibly be a drag/drop target?  The test here is
1215     * a combination of the above "visible now" with the check that the
1216     * Input Manager uses when discarding windows from input consideration.
1217     */
1218    boolean isPotentialDragTarget() {
1219        return isVisibleNow() && !mRemoved
1220                && mInputChannel != null && mInputWindowHandle != null;
1221    }
1222
1223    /**
1224     * Same as isVisible(), but we also count it as visible between the
1225     * call to IWindowSession.add() and the first relayout().
1226     */
1227    boolean isVisibleOrAdding() {
1228        final AppWindowToken atoken = mAppToken;
1229        return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
1230                && mPolicyVisibility && !mAttachedHidden
1231                && (atoken == null || !atoken.hiddenRequested)
1232                && !mAnimatingExit && !mDestroying;
1233    }
1234
1235    /**
1236     * Is this window currently on-screen?  It is on-screen either if it
1237     * is visible or it is currently running an animation before no longer
1238     * being visible.
1239     */
1240    boolean isOnScreen() {
1241        return mPolicyVisibility && isOnScreenIgnoringKeyguard();
1242    }
1243
1244    /**
1245     * Like isOnScreen(), but ignores any force hiding of the window due
1246     * to the keyguard.
1247     */
1248    boolean isOnScreenIgnoringKeyguard() {
1249        if (!mHasSurface || mDestroying) {
1250            return false;
1251        }
1252        final AppWindowToken atoken = mAppToken;
1253        if (atoken != null) {
1254            return ((!mAttachedHidden && !atoken.hiddenRequested)
1255                    || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null);
1256        }
1257        return !mAttachedHidden || mWinAnimator.mAnimation != null;
1258    }
1259
1260    /**
1261     * Whether this window's drawn state might affect the drawn states of the app token.
1262     *
1263     * @param visibleOnly Whether we should consider only the windows that's currently
1264     *                    visible in layout. If true, windows that has not relayout to VISIBLE
1265     *                    would always return false.
1266     *
1267     * @return true if the window should be considered while evaluating allDrawn flags.
1268     */
1269    boolean mightAffectAllDrawn(boolean visibleOnly) {
1270        final boolean isViewVisible = (mAppToken == null || !mAppToken.clientHidden)
1271                && (mViewVisibility == View.VISIBLE) && !mWindowRemovalAllowed;
1272        return (isOnScreenIgnoringKeyguard() && (!visibleOnly || isViewVisible)
1273                || mWinAnimator.mAttrType == TYPE_BASE_APPLICATION)
1274                && !mAnimatingExit && !mDestroying;
1275    }
1276
1277    /**
1278     * Whether this window is "interesting" when evaluating allDrawn. If it's interesting,
1279     * it must be drawn before allDrawn can become true.
1280     */
1281    boolean isInteresting() {
1282        return mAppToken != null && !mAppDied
1283                && (!mAppToken.mAppAnimator.freezingScreen || !mAppFreezing);
1284    }
1285
1286    /**
1287     * Like isOnScreen(), but we don't return true if the window is part
1288     * of a transition that has not yet been started.
1289     */
1290    boolean isReadyForDisplay() {
1291        if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
1292            return false;
1293        }
1294        return mHasSurface && mPolicyVisibility && !mDestroying
1295                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden)
1296                        || mWinAnimator.mAnimation != null
1297                        || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
1298    }
1299
1300    /**
1301     * Like isReadyForDisplay(), but ignores any force hiding of the window due
1302     * to the keyguard.
1303     */
1304    boolean isReadyForDisplayIgnoringKeyguard() {
1305        if (mRootToken.waitingToShow && mService.mAppTransition.isTransitionSet()) {
1306            return false;
1307        }
1308        final AppWindowToken atoken = mAppToken;
1309        if (atoken == null && !mPolicyVisibility) {
1310            // If this is not an app window, and the policy has asked to force
1311            // hide, then we really do want to hide.
1312            return false;
1313        }
1314        return mHasSurface && !mDestroying
1315                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE && !mRootToken.hidden)
1316                        || mWinAnimator.mAnimation != null
1317                        || ((atoken != null) && (atoken.mAppAnimator.animation != null)
1318                                && !mWinAnimator.isDummyAnimation()));
1319    }
1320
1321    /**
1322     * Like isOnScreen, but returns false if the surface hasn't yet
1323     * been drawn.
1324     */
1325    @Override
1326    public boolean isDisplayedLw() {
1327        final AppWindowToken atoken = mAppToken;
1328        return isDrawnLw() && mPolicyVisibility
1329            && ((!mAttachedHidden &&
1330                    (atoken == null || !atoken.hiddenRequested))
1331                        || mWinAnimator.mAnimating
1332                        || (atoken != null && atoken.mAppAnimator.animation != null));
1333    }
1334
1335    /**
1336     * Return true if this window or its app token is currently animating.
1337     */
1338    @Override
1339    public boolean isAnimatingLw() {
1340        return mWinAnimator.mAnimation != null
1341                || (mAppToken != null && mAppToken.mAppAnimator.animation != null);
1342    }
1343
1344    @Override
1345    public boolean isGoneForLayoutLw() {
1346        final AppWindowToken atoken = mAppToken;
1347        return mViewVisibility == View.GONE
1348                || !mRelayoutCalled
1349                || (atoken == null && mRootToken.hidden)
1350                || (atoken != null && atoken.hiddenRequested)
1351                || mAttachedHidden
1352                || (mAnimatingExit && !isAnimatingLw())
1353                || mDestroying;
1354    }
1355
1356    /**
1357     * Returns true if the window has a surface that it has drawn a
1358     * complete UI in to.
1359     */
1360    public boolean isDrawFinishedLw() {
1361        return mHasSurface && !mDestroying &&
1362                (mWinAnimator.mDrawState == WindowStateAnimator.COMMIT_DRAW_PENDING
1363                || mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW
1364                || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN);
1365    }
1366
1367    /**
1368     * Returns true if the window has a surface that it has drawn a
1369     * complete UI in to.
1370     */
1371    @Override
1372    public boolean isDrawnLw() {
1373        return mHasSurface && !mDestroying &&
1374                (mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW
1375                || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN);
1376    }
1377
1378    /**
1379     * Return true if the window is opaque and fully drawn.  This indicates
1380     * it may obscure windows behind it.
1381     */
1382    boolean isOpaqueDrawn() {
1383        // When there is keyguard, wallpaper could be placed over the secure app
1384        // window but invisible. We need to check wallpaper visibility explicitly
1385        // to determine if it's occluding apps.
1386        return ((!mIsWallpaper && mAttrs.format == PixelFormat.OPAQUE)
1387                || (mIsWallpaper && mWallpaperVisible))
1388                && isDrawnLw() && mWinAnimator.mAnimation == null
1389                && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
1390    }
1391
1392    /**
1393     * Return whether this window has moved. (Only makes
1394     * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
1395     */
1396    boolean hasMoved() {
1397        return mHasSurface && (mContentChanged || mMovedByResize)
1398                && !mAnimatingExit && mService.okToDisplay()
1399                && (mFrame.top != mLastFrame.top || mFrame.left != mLastFrame.left)
1400                && (mAttachedWindow == null || !mAttachedWindow.hasMoved());
1401    }
1402
1403    boolean isObscuringFullscreen(final DisplayInfo displayInfo) {
1404        Task task = getTask();
1405        if (task != null && task.mStack != null && !task.mStack.isFullscreen()) {
1406            return false;
1407        }
1408        if (!isOpaqueDrawn() || !isFrameFullscreen(displayInfo)) {
1409            return false;
1410        }
1411        return true;
1412    }
1413
1414    boolean isFrameFullscreen(final DisplayInfo displayInfo) {
1415        return mFrame.left <= 0 && mFrame.top <= 0
1416                && mFrame.right >= displayInfo.appWidth && mFrame.bottom >= displayInfo.appHeight;
1417    }
1418
1419    boolean isConfigChanged() {
1420        getMergedConfig(mTmpConfig);
1421
1422        // If the merged configuration is still empty, it means that we haven't issues the
1423        // configuration to the client yet and we need to return true so the configuration updates.
1424        boolean configChanged = mMergedConfiguration.equals(Configuration.EMPTY)
1425                || mTmpConfig.diff(mMergedConfiguration) != 0;
1426
1427        if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
1428            // Retain configuration changed status until resetConfiguration called.
1429            mConfigHasChanged |= configChanged;
1430            configChanged = mConfigHasChanged;
1431        }
1432
1433        return configChanged;
1434    }
1435
1436    boolean isAdjustedForMinimizedDock() {
1437        return mAppToken != null && mAppToken.mTask != null
1438                && mAppToken.mTask.mStack.isAdjustedForMinimizedDock();
1439    }
1440
1441    void removeLocked() {
1442        disposeInputChannel();
1443
1444        if (isChildWindow()) {
1445            if (DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
1446            mAttachedWindow.mChildWindows.remove(this);
1447        }
1448        mWinAnimator.destroyDeferredSurfaceLocked();
1449        mWinAnimator.destroySurfaceLocked();
1450        mSession.windowRemovedLocked();
1451        try {
1452            mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
1453        } catch (RuntimeException e) {
1454            // Ignore if it has already been removed (usually because
1455            // we are doing this as part of processing a death note.)
1456        }
1457    }
1458
1459    void setHasSurface(boolean hasSurface) {
1460        mHasSurface = hasSurface;
1461    }
1462
1463    int getAnimLayerAdjustment() {
1464        if (mTargetAppToken != null) {
1465            return mTargetAppToken.mAppAnimator.animLayerAdjustment;
1466        } else if (mAppToken != null) {
1467            return mAppToken.mAppAnimator.animLayerAdjustment;
1468        } else {
1469            // Nothing is animating, so there is no animation adjustment.
1470            return 0;
1471        }
1472    }
1473
1474    void scheduleAnimationIfDimming() {
1475        if (mDisplayContent == null) {
1476            return;
1477        }
1478        final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
1479        if (dimLayerUser != null && mDisplayContent.mDimLayerController.isDimming(
1480                dimLayerUser, mWinAnimator)) {
1481            // Force an animation pass just to update the mDimLayer layer.
1482            mService.scheduleAnimationLocked();
1483        }
1484    }
1485
1486    /**
1487     * Notifies this window that the corresponding task has just moved in the stack.
1488     * <p>
1489     * This is used to fix the following: If we moved in the stack, and if the last clip rect was
1490     * empty, meaning that our task was completely offscreen, we need to keep it invisible because
1491     * the actual app transition that updates the visibility is delayed by a few transactions.
1492     * Instead of messing around with the ordering and timing how transitions and transactions are
1493     * executed, we introduce this little hack which prevents this window of getting visible again
1494     * with the wrong bounds until the app transitions has started.
1495     * <p>
1496     * This method notifies the window about that we just moved in the stack so we can apply this
1497     * logic in {@link WindowStateAnimator#updateSurfaceWindowCrop}
1498     */
1499    void notifyMovedInStack() {
1500        mJustMovedInStack = true;
1501    }
1502
1503    /**
1504     * See {@link #notifyMovedInStack}.
1505     *
1506     * @return Whether we just got moved in the corresponding stack.
1507     */
1508    boolean hasJustMovedInStack() {
1509        return mJustMovedInStack;
1510    }
1511
1512    /**
1513     * Resets that we just moved in the corresponding stack. See {@link #notifyMovedInStack}.
1514     */
1515    void resetJustMovedInStack() {
1516        mJustMovedInStack = false;
1517    }
1518
1519    private final class DeadWindowEventReceiver extends InputEventReceiver {
1520        DeadWindowEventReceiver(InputChannel inputChannel) {
1521            super(inputChannel, mService.mH.getLooper());
1522        }
1523        @Override
1524        public void onInputEvent(InputEvent event) {
1525            finishInputEvent(event, true);
1526        }
1527    }
1528    /**
1529     *  Dummy event receiver for windows that died visible.
1530     */
1531    private DeadWindowEventReceiver mDeadWindowEventReceiver;
1532
1533    void openInputChannel(InputChannel outInputChannel) {
1534        if (mInputChannel != null) {
1535            throw new IllegalStateException("Window already has an input channel.");
1536        }
1537        String name = makeInputChannelName();
1538        InputChannel[] inputChannels = InputChannel.openInputChannelPair(name);
1539        mInputChannel = inputChannels[0];
1540        mClientChannel = inputChannels[1];
1541        mInputWindowHandle.inputChannel = inputChannels[0];
1542        if (outInputChannel != null) {
1543            mClientChannel.transferTo(outInputChannel);
1544            mClientChannel.dispose();
1545            mClientChannel = null;
1546        } else {
1547            // If the window died visible, we setup a dummy input channel, so that taps
1548            // can still detected by input monitor channel, and we can relaunch the app.
1549            // Create dummy event receiver that simply reports all events as handled.
1550            mDeadWindowEventReceiver = new DeadWindowEventReceiver(mClientChannel);
1551        }
1552        mService.mInputManager.registerInputChannel(mInputChannel, mInputWindowHandle);
1553    }
1554
1555    void disposeInputChannel() {
1556        if (mDeadWindowEventReceiver != null) {
1557            mDeadWindowEventReceiver.dispose();
1558            mDeadWindowEventReceiver = null;
1559        }
1560
1561        // unregister server channel first otherwise it complains about broken channel
1562        if (mInputChannel != null) {
1563            mService.mInputManager.unregisterInputChannel(mInputChannel);
1564            mInputChannel.dispose();
1565            mInputChannel = null;
1566        }
1567        if (mClientChannel != null) {
1568            mClientChannel.dispose();
1569            mClientChannel = null;
1570        }
1571        mInputWindowHandle.inputChannel = null;
1572    }
1573
1574    void applyDimLayerIfNeeded() {
1575        // When the app is terminated (eg. from Recents), the task might have already been
1576        // removed with the window pending removal. Don't apply dim in such cases, as there
1577        // will be no more updateDimLayer() calls, which leaves the dimlayer invalid.
1578        final AppWindowToken token = mAppToken;
1579        if (token != null && token.removed) {
1580            return;
1581        }
1582
1583        if (!mAnimatingExit && mAppDied) {
1584            // If app died visible, apply a dim over the window to indicate that it's inactive
1585            mDisplayContent.mDimLayerController.applyDimAbove(getDimLayerUser(), mWinAnimator);
1586        } else if ((mAttrs.flags & FLAG_DIM_BEHIND) != 0
1587                && mDisplayContent != null && !mAnimatingExit && isVisibleUnchecked()) {
1588            mDisplayContent.mDimLayerController.applyDimBehind(getDimLayerUser(), mWinAnimator);
1589        }
1590    }
1591
1592    DimLayer.DimLayerUser getDimLayerUser() {
1593        Task task = getTask();
1594        if (task != null) {
1595            return task;
1596        }
1597        return getStack();
1598    }
1599
1600    void maybeRemoveReplacedWindow() {
1601        if (mAppToken == null) {
1602            return;
1603        }
1604        for (int i = mAppToken.allAppWindows.size() - 1; i >= 0; i--) {
1605            final WindowState win = mAppToken.allAppWindows.get(i);
1606            if (win.mWillReplaceWindow && win.mReplacingWindow == this && hasDrawnLw()) {
1607                if (DEBUG_ADD_REMOVE) Slog.d(TAG, "Removing replaced window: " + win);
1608                if (win.isDimming()) {
1609                    win.transferDimToReplacement();
1610                }
1611                win.mWillReplaceWindow = false;
1612                final boolean animateReplacingWindow = win.mAnimateReplacingWindow;
1613                win.mAnimateReplacingWindow = false;
1614                win.mReplacingRemoveRequested = false;
1615                win.mReplacingWindow = null;
1616                mSkipEnterAnimationForSeamlessReplacement = false;
1617                if (win.mAnimatingExit || !animateReplacingWindow) {
1618                    mService.removeWindowInnerLocked(win);
1619                }
1620            }
1621        }
1622    }
1623
1624    void setDisplayLayoutNeeded() {
1625        if (mDisplayContent != null) {
1626            mDisplayContent.layoutNeeded = true;
1627        }
1628    }
1629
1630    boolean inDockedWorkspace() {
1631        final Task task = getTask();
1632        return task != null && task.inDockedWorkspace();
1633    }
1634
1635    // TODO: Strange usage of word workspace here and above.
1636    boolean inPinnedWorkspace() {
1637        final Task task = getTask();
1638        return task != null && task.inPinnedWorkspace();
1639    }
1640
1641    boolean isDockedInEffect() {
1642        final Task task = getTask();
1643        return task != null && task.isDockedInEffect();
1644    }
1645
1646    void applyScrollIfNeeded() {
1647        final Task task = getTask();
1648        if (task != null) {
1649            task.applyScrollToWindowIfNeeded(this);
1650        }
1651    }
1652
1653    void applyAdjustForImeIfNeeded() {
1654        final Task task = getTask();
1655        if (task != null && task.mStack != null && task.mStack.isAdjustedForIme()) {
1656            task.mStack.applyAdjustForImeIfNeeded(task);
1657        }
1658    }
1659
1660    int getTouchableRegion(Region region, int flags) {
1661        final boolean modal = (flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
1662        if (modal && mAppToken != null) {
1663            // Limit the outer touch to the activity stack region.
1664            flags |= FLAG_NOT_TOUCH_MODAL;
1665            // If this is a modal window we need to dismiss it if it's not full screen and the
1666            // touch happens outside of the frame that displays the content. This means we
1667            // need to intercept touches outside of that window. The dim layer user
1668            // associated with the window (task or stack) will give us the good bounds, as
1669            // they would be used to display the dim layer.
1670            final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
1671            if (dimLayerUser != null) {
1672                dimLayerUser.getDimBounds(mTmpRect);
1673            } else {
1674                getVisibleBounds(mTmpRect);
1675            }
1676            if (inFreeformWorkspace()) {
1677                // For freeform windows we the touch region to include the whole surface for the
1678                // shadows.
1679                final DisplayMetrics displayMetrics = getDisplayContent().getDisplayMetrics();
1680                final int delta = WindowManagerService.dipToPixel(
1681                        RESIZE_HANDLE_WIDTH_IN_DP, displayMetrics);
1682                mTmpRect.inset(-delta, -delta);
1683            }
1684            region.set(mTmpRect);
1685            cropRegionToStackBoundsIfNeeded(region);
1686        } else {
1687            // Not modal or full screen modal
1688            getTouchableRegion(region);
1689        }
1690        return flags;
1691    }
1692
1693    void checkPolicyVisibilityChange() {
1694        if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
1695            if (DEBUG_VISIBILITY) {
1696                Slog.v(TAG, "Policy visibility changing after anim in " +
1697                        mWinAnimator + ": " + mPolicyVisibilityAfterAnim);
1698            }
1699            mPolicyVisibility = mPolicyVisibilityAfterAnim;
1700            setDisplayLayoutNeeded();
1701            if (!mPolicyVisibility) {
1702                if (mService.mCurrentFocus == this) {
1703                    if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
1704                            "setAnimationLocked: setting mFocusMayChange true");
1705                    mService.mFocusMayChange = true;
1706                }
1707                // Window is no longer visible -- make sure if we were waiting
1708                // for it to be displayed before enabling the display, that
1709                // we allow the display to be enabled now.
1710                mService.enableScreenIfNeededLocked();
1711            }
1712        }
1713    }
1714
1715    void setRequestedSize(int requestedWidth, int requestedHeight) {
1716        if ((mRequestedWidth != requestedWidth || mRequestedHeight != requestedHeight)) {
1717            mLayoutNeeded = true;
1718            mRequestedWidth = requestedWidth;
1719            mRequestedHeight = requestedHeight;
1720        }
1721    }
1722
1723    void prepareWindowToDisplayDuringRelayout(Configuration outConfig) {
1724        if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
1725                == SOFT_INPUT_ADJUST_RESIZE) {
1726            mLayoutNeeded = true;
1727        }
1728        if (isDrawnLw() && mService.okToDisplay()) {
1729            mWinAnimator.applyEnterAnimationLocked();
1730        }
1731        if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
1732            if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
1733            mTurnOnScreen = true;
1734        }
1735        if (isConfigChanged()) {
1736            final Configuration newConfig = updateConfiguration();
1737            if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + this + " visible with new config: "
1738                    + newConfig);
1739            outConfig.setTo(newConfig);
1740        }
1741    }
1742
1743    void adjustStartingWindowFlags() {
1744        if (mAttrs.type == TYPE_BASE_APPLICATION && mAppToken != null
1745                && mAppToken.startingWindow != null) {
1746            // Special handling of starting window over the base
1747            // window of the app: propagate lock screen flags to it,
1748            // to provide the correct semantics while starting.
1749            final int mask = FLAG_SHOW_WHEN_LOCKED | FLAG_DISMISS_KEYGUARD
1750                    | FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
1751            WindowManager.LayoutParams sa = mAppToken.startingWindow.mAttrs;
1752            sa.flags = (sa.flags & ~mask) | (mAttrs.flags & mask);
1753        }
1754    }
1755
1756    void setWindowScale(int requestedWidth, int requestedHeight) {
1757        final boolean scaledWindow = (mAttrs.flags & FLAG_SCALED) != 0;
1758
1759        if (scaledWindow) {
1760            // requested{Width|Height} Surface's physical size
1761            // attrs.{width|height} Size on screen
1762            // TODO: We don't check if attrs != null here. Is it implicitly checked?
1763            mHScale = (mAttrs.width  != requestedWidth)  ?
1764                    (mAttrs.width  / (float)requestedWidth) : 1.0f;
1765            mVScale = (mAttrs.height != requestedHeight) ?
1766                    (mAttrs.height / (float)requestedHeight) : 1.0f;
1767        } else {
1768            mHScale = mVScale = 1;
1769        }
1770    }
1771
1772    private class DeathRecipient implements IBinder.DeathRecipient {
1773        @Override
1774        public void binderDied() {
1775            try {
1776                synchronized(mService.mWindowMap) {
1777                    WindowState win = mService.windowForClientLocked(mSession, mClient, false);
1778                    Slog.i(TAG, "WIN DEATH: " + win);
1779                    if (win != null) {
1780                        mService.removeWindowLocked(win, shouldKeepVisibleDeadAppWindow());
1781                        if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
1782                            // The owner of the docked divider died :( We reset the docked stack,
1783                            // just in case they have the divider at an unstable position. Better
1784                            // also reset drag resizing state, because the owner can't do it
1785                            // anymore.
1786                            final TaskStack stack = mService.mStackIdToStack.get(DOCKED_STACK_ID);
1787                            if (stack != null) {
1788                                stack.resetDockedStackToMiddle();
1789                            }
1790                            mService.setDockedStackResizing(false);
1791                        }
1792                    } else if (mHasSurface) {
1793                        Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
1794                        mService.removeWindowLocked(WindowState.this);
1795                    }
1796                }
1797            } catch (IllegalArgumentException ex) {
1798                // This will happen if the window has already been removed.
1799            }
1800        }
1801    }
1802
1803    /**
1804     * Returns true if this window is visible and belongs to a dead app and shouldn't be removed,
1805     * because we want to preserve its location on screen to be re-activated later when the user
1806     * interacts with it.
1807     */
1808    boolean shouldKeepVisibleDeadAppWindow() {
1809        if (!isWinVisibleLw() || mAppToken == null || mAppToken.clientHidden) {
1810            // Not a visible app window or the app isn't dead.
1811            return false;
1812        }
1813
1814        if (mAttrs.token != mClient.asBinder()) {
1815            // The window was add by a client using another client's app token. We don't want to
1816            // keep the dead window around for this case since this is meant for 'real' apps.
1817            return false;
1818        }
1819
1820        if (mAttrs.type == TYPE_APPLICATION_STARTING) {
1821            // We don't keep starting windows since they were added by the window manager before
1822            // the app even launched.
1823            return false;
1824        }
1825
1826        final TaskStack stack = getStack();
1827        return stack != null && StackId.keepVisibleDeadAppWindowOnScreen(stack.mStackId);
1828    }
1829
1830    /** @return true if this window desires key events. */
1831    boolean canReceiveKeys() {
1832        return isVisibleOrAdding()
1833                && (mViewVisibility == View.VISIBLE) && !mRemoveOnExit
1834                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0)
1835                && (mAppToken == null || mAppToken.windowsAreFocusable())
1836                && !isAdjustedForMinimizedDock();
1837    }
1838
1839    @Override
1840    public boolean hasDrawnLw() {
1841        return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
1842    }
1843
1844    @Override
1845    public boolean showLw(boolean doAnimation) {
1846        return showLw(doAnimation, true);
1847    }
1848
1849    boolean showLw(boolean doAnimation, boolean requestAnim) {
1850        if (isHiddenFromUserLocked()) {
1851            return false;
1852        }
1853        if (!mAppOpVisibility) {
1854            // Being hidden due to app op request.
1855            return false;
1856        }
1857        if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
1858            // Already showing.
1859            return false;
1860        }
1861        if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
1862        if (doAnimation) {
1863            if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
1864                    + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation);
1865            if (!mService.okToDisplay()) {
1866                doAnimation = false;
1867            } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) {
1868                // Check for the case where we are currently visible and
1869                // not animating; we do not want to do animation at such a
1870                // point to become visible when we already are.
1871                doAnimation = false;
1872            }
1873        }
1874        mPolicyVisibility = true;
1875        mPolicyVisibilityAfterAnim = true;
1876        if (doAnimation) {
1877            mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
1878        }
1879        if (requestAnim) {
1880            mService.scheduleAnimationLocked();
1881        }
1882        return true;
1883    }
1884
1885    @Override
1886    public boolean hideLw(boolean doAnimation) {
1887        return hideLw(doAnimation, true);
1888    }
1889
1890    boolean hideLw(boolean doAnimation, boolean requestAnim) {
1891        if (doAnimation) {
1892            if (!mService.okToDisplay()) {
1893                doAnimation = false;
1894            }
1895        }
1896        boolean current = doAnimation ? mPolicyVisibilityAfterAnim
1897                : mPolicyVisibility;
1898        if (!current) {
1899            // Already hiding.
1900            return false;
1901        }
1902        if (doAnimation) {
1903            mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
1904            if (mWinAnimator.mAnimation == null) {
1905                doAnimation = false;
1906            }
1907        }
1908        if (doAnimation) {
1909            mPolicyVisibilityAfterAnim = false;
1910        } else {
1911            if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
1912            mPolicyVisibilityAfterAnim = false;
1913            mPolicyVisibility = false;
1914            // Window is no longer visible -- make sure if we were waiting
1915            // for it to be displayed before enabling the display, that
1916            // we allow the display to be enabled now.
1917            mService.enableScreenIfNeededLocked();
1918            if (mService.mCurrentFocus == this) {
1919                if (DEBUG_FOCUS_LIGHT) Slog.i(TAG,
1920                        "WindowState.hideLw: setting mFocusMayChange true");
1921                mService.mFocusMayChange = true;
1922            }
1923        }
1924        if (requestAnim) {
1925            mService.scheduleAnimationLocked();
1926        }
1927        return true;
1928    }
1929
1930    public void setAppOpVisibilityLw(boolean state) {
1931        if (mAppOpVisibility != state) {
1932            mAppOpVisibility = state;
1933            if (state) {
1934                // If the policy visibility had last been to hide, then this
1935                // will incorrectly show at this point since we lost that
1936                // information.  Not a big deal -- for the windows that have app
1937                // ops modifies they should only be hidden by policy due to the
1938                // lock screen, and the user won't be changing this if locked.
1939                // Plus it will quickly be fixed the next time we do a layout.
1940                showLw(true, true);
1941            } else {
1942                hideLw(true, true);
1943            }
1944        }
1945    }
1946
1947    public void pokeDrawLockLw(long timeout) {
1948        if (isVisibleOrAdding()) {
1949            if (mDrawLock == null) {
1950                // We want the tag name to be somewhat stable so that it is easier to correlate
1951                // in wake lock statistics.  So in particular, we don't want to include the
1952                // window's hash code as in toString().
1953                final CharSequence tag = getWindowTag();
1954                mDrawLock = mService.mPowerManager.newWakeLock(
1955                        PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
1956                mDrawLock.setReferenceCounted(false);
1957                mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
1958            }
1959            // Each call to acquire resets the timeout.
1960            if (DEBUG_POWER) {
1961                Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by "
1962                        + mAttrs.packageName);
1963            }
1964            mDrawLock.acquire(timeout);
1965        } else if (DEBUG_POWER) {
1966            Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window "
1967                    + "owned by " + mAttrs.packageName);
1968        }
1969    }
1970
1971    @Override
1972    public boolean isAlive() {
1973        return mClient.asBinder().isBinderAlive();
1974    }
1975
1976    boolean isClosing() {
1977        return mAnimatingExit || (mService.mClosingApps.contains(mAppToken));
1978    }
1979
1980    boolean isAnimatingWithSavedSurface() {
1981        return mAnimatingWithSavedSurface;
1982    }
1983
1984    boolean isAnimatingInvisibleWithSavedSurface() {
1985        return mAnimatingWithSavedSurface
1986                && (mViewVisibility != View.VISIBLE || mWindowRemovalAllowed);
1987    }
1988
1989    public void setVisibleBeforeClientHidden() {
1990        mWasVisibleBeforeClientHidden |=
1991                (mViewVisibility == View.VISIBLE || mAnimatingWithSavedSurface);
1992    }
1993
1994    public void clearVisibleBeforeClientHidden() {
1995        mWasVisibleBeforeClientHidden = false;
1996    }
1997
1998    public boolean wasVisibleBeforeClientHidden() {
1999        return mWasVisibleBeforeClientHidden;
2000    }
2001
2002    private boolean shouldSaveSurface() {
2003        if (mWinAnimator.mSurfaceController == null) {
2004            // Don't bother if the surface controller is gone for any reason.
2005            return false;
2006        }
2007
2008        if (!mWasVisibleBeforeClientHidden) {
2009            return false;
2010        }
2011
2012        if ((mAttrs.flags & FLAG_SECURE) != 0) {
2013            // We don't save secure surfaces since their content shouldn't be shown while the app
2014            // isn't on screen and content might leak through during the transition animation with
2015            // saved surface.
2016            return false;
2017        }
2018
2019        if (ActivityManager.isLowRamDeviceStatic()) {
2020            // Don't save surfaces on Svelte devices.
2021            return false;
2022        }
2023
2024        Task task = getTask();
2025        if (task == null || task.inHomeStack()) {
2026            // Don't save surfaces for home stack apps. These usually resume and draw
2027            // first frame very fast. Saving surfaces are mostly a waste of memory.
2028            return false;
2029        }
2030
2031        final AppWindowToken taskTop = task.getTopVisibleAppToken();
2032        if (taskTop != null && taskTop != mAppToken) {
2033            // Don't save if the window is not the topmost window.
2034            return false;
2035        }
2036
2037        if (mResizedWhileGone) {
2038            // Somebody resized our window while we were gone for layout, which means that the
2039            // client got an old size, so we have an outdated surface here.
2040            return false;
2041        }
2042
2043        if (DEBUG_DISABLE_SAVING_SURFACES) {
2044            return false;
2045        }
2046
2047        return mAppToken.shouldSaveSurface();
2048    }
2049
2050    static final Region sEmptyRegion = new Region();
2051
2052    void destroyOrSaveSurface() {
2053        mSurfaceSaved = shouldSaveSurface();
2054        if (mSurfaceSaved) {
2055            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2056                Slog.v(TAG, "Saving surface: " + this);
2057            }
2058            // Previous user of the surface may have set a transparent region signaling a portion
2059            // doesn't need to be composited, so reset to default empty state.
2060            mSession.setTransparentRegion(mClient, sEmptyRegion);
2061
2062            mWinAnimator.hide("saved surface");
2063            mWinAnimator.mDrawState = WindowStateAnimator.NO_SURFACE;
2064            setHasSurface(false);
2065            // The client should have disconnected at this point, but if it doesn't,
2066            // we need to make sure it's disconnected. Otherwise when we reuse the surface
2067            // the client can't reconnect to the buffer queue, and rendering will fail.
2068            if (mWinAnimator.mSurfaceController != null) {
2069                mWinAnimator.mSurfaceController.disconnectInTransaction();
2070            }
2071            mAnimatingWithSavedSurface = false;
2072        } else {
2073            mWinAnimator.destroySurfaceLocked();
2074        }
2075        // Clear animating flags now, since the surface is now gone. (Note this is true even
2076        // if the surface is saved, to outside world the surface is still NO_SURFACE.)
2077        mAnimatingExit = false;
2078    }
2079
2080    void destroySavedSurface() {
2081        if (mSurfaceSaved) {
2082            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2083                Slog.v(TAG, "Destroying saved surface: " + this);
2084            }
2085            mWinAnimator.destroySurfaceLocked();
2086        }
2087        mWasVisibleBeforeClientHidden = false;
2088    }
2089
2090    void restoreSavedSurface() {
2091        if (!mSurfaceSaved) {
2092            return;
2093        }
2094        mSurfaceSaved = false;
2095        if (mWinAnimator.mSurfaceController != null) {
2096            setHasSurface(true);
2097            mWinAnimator.mDrawState = WindowStateAnimator.READY_TO_SHOW;
2098            mAnimatingWithSavedSurface = true;
2099
2100            if (DEBUG_APP_TRANSITIONS || DEBUG_ANIM) {
2101                Slog.v(TAG, "Restoring saved surface: " + this);
2102            }
2103        } else {
2104            // mSurfaceController shouldn't be null if mSurfaceSaved was still true at
2105            // this point. Even if we destroyed the saved surface because of rotation
2106            // or resize, mSurfaceSaved flag should have been cleared. So this is a wtf.
2107            Slog.wtf(TAG, "Failed to restore saved surface: surface gone! " + this);
2108        }
2109    }
2110
2111    boolean canRestoreSurface() {
2112        return mWasVisibleBeforeClientHidden && mSurfaceSaved;
2113    }
2114
2115    boolean hasSavedSurface() {
2116        return mSurfaceSaved;
2117    }
2118
2119    void clearHasSavedSurface() {
2120        mSurfaceSaved = false;
2121        mAnimatingWithSavedSurface = false;
2122        if (mWasVisibleBeforeClientHidden) {
2123            mAppToken.destroySavedSurfaces();
2124        }
2125    }
2126
2127    boolean clearAnimatingWithSavedSurface() {
2128        if (mAnimatingWithSavedSurface) {
2129            // App has drawn something to its windows, we're no longer animating with
2130            // the saved surfaces.
2131            if (DEBUG_ANIM) Slog.d(TAG,
2132                    "clearAnimatingWithSavedSurface(): win=" + this);
2133            mAnimatingWithSavedSurface = false;
2134            return true;
2135        }
2136        return false;
2137    }
2138
2139    @Override
2140    public boolean isDefaultDisplay() {
2141        final DisplayContent displayContent = getDisplayContent();
2142        if (displayContent == null) {
2143            // Only a window that was on a non-default display can be detached from it.
2144            return false;
2145        }
2146        return displayContent.isDefaultDisplay;
2147    }
2148
2149    @Override
2150    public boolean isDimming() {
2151        final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
2152        return dimLayerUser != null && mDisplayContent != null &&
2153                mDisplayContent.mDimLayerController.isDimming(dimLayerUser, mWinAnimator);
2154    }
2155
2156    public void setShowToOwnerOnlyLocked(boolean showToOwnerOnly) {
2157        mShowToOwnerOnly = showToOwnerOnly;
2158    }
2159
2160    boolean isHiddenFromUserLocked() {
2161        // Attached windows are evaluated based on the window that they are attached to.
2162        WindowState win = this;
2163        while (win.isChildWindow()) {
2164            win = win.mAttachedWindow;
2165        }
2166        if (win.mAttrs.type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW
2167                && win.mAppToken != null && win.mAppToken.showForAllUsers) {
2168
2169            // All window frames that are fullscreen extend above status bar, but some don't extend
2170            // below navigation bar. Thus, check for display frame for top/left and stable frame for
2171            // bottom right.
2172            if (win.mFrame.left <= win.mDisplayFrame.left
2173                    && win.mFrame.top <= win.mDisplayFrame.top
2174                    && win.mFrame.right >= win.mStableFrame.right
2175                    && win.mFrame.bottom >= win.mStableFrame.bottom) {
2176                // Is a fullscreen window, like the clock alarm. Show to everyone.
2177                return false;
2178            }
2179        }
2180
2181        return win.mShowToOwnerOnly
2182                && !mService.isCurrentProfileLocked(UserHandle.getUserId(win.mOwnerUid));
2183    }
2184
2185    private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
2186        outRegion.set(
2187                frame.left + inset.left, frame.top + inset.top,
2188                frame.right - inset.right, frame.bottom - inset.bottom);
2189    }
2190
2191    void getTouchableRegion(Region outRegion) {
2192        final Rect frame = mFrame;
2193        switch (mTouchableInsets) {
2194            default:
2195            case TOUCHABLE_INSETS_FRAME:
2196                outRegion.set(frame);
2197                break;
2198            case TOUCHABLE_INSETS_CONTENT:
2199                applyInsets(outRegion, frame, mGivenContentInsets);
2200                break;
2201            case TOUCHABLE_INSETS_VISIBLE:
2202                applyInsets(outRegion, frame, mGivenVisibleInsets);
2203                break;
2204            case TOUCHABLE_INSETS_REGION: {
2205                final Region givenTouchableRegion = mGivenTouchableRegion;
2206                outRegion.set(givenTouchableRegion);
2207                outRegion.translate(frame.left, frame.top);
2208                break;
2209            }
2210        }
2211        cropRegionToStackBoundsIfNeeded(outRegion);
2212    }
2213
2214    void cropRegionToStackBoundsIfNeeded(Region region) {
2215        final Task task = getTask();
2216        if (task == null || !task.cropWindowsToStackBounds()) {
2217            return;
2218        }
2219
2220        final TaskStack stack = task.mStack;
2221        if (stack == null) {
2222            return;
2223        }
2224
2225        stack.getDimBounds(mTmpRect);
2226        region.op(mTmpRect, Region.Op.INTERSECT);
2227    }
2228
2229    WindowList getWindowList() {
2230        final DisplayContent displayContent = getDisplayContent();
2231        return displayContent == null ? null : displayContent.getWindowList();
2232    }
2233
2234    /**
2235     * Report a focus change.  Must be called with no locks held, and consistently
2236     * from the same serialized thread (such as dispatched from a handler).
2237     */
2238    public void reportFocusChangedSerialized(boolean focused, boolean inTouchMode) {
2239        try {
2240            mClient.windowFocusChanged(focused, inTouchMode);
2241        } catch (RemoteException e) {
2242        }
2243        if (mFocusCallbacks != null) {
2244            final int N = mFocusCallbacks.beginBroadcast();
2245            for (int i=0; i<N; i++) {
2246                IWindowFocusObserver obs = mFocusCallbacks.getBroadcastItem(i);
2247                try {
2248                    if (focused) {
2249                        obs.focusGained(mWindowId.asBinder());
2250                    } else {
2251                        obs.focusLost(mWindowId.asBinder());
2252                    }
2253                } catch (RemoteException e) {
2254                }
2255            }
2256            mFocusCallbacks.finishBroadcast();
2257        }
2258    }
2259
2260    /**
2261     * Update our current configurations, based on task configuration.
2262     *
2263     * @return A configuration suitable for sending to the client.
2264     */
2265    private Configuration updateConfiguration() {
2266        final boolean configChanged = isConfigChanged();
2267        getMergedConfig(mMergedConfiguration);
2268        mConfigHasChanged = false;
2269        if ((DEBUG_RESIZE || DEBUG_ORIENTATION || DEBUG_CONFIGURATION) && configChanged) {
2270            Slog.i(TAG, "Sending new config to window " + this + ": " +
2271                    " / mergedConfig=" + mMergedConfiguration);
2272        }
2273        return mMergedConfiguration;
2274    }
2275
2276    private void getMergedConfig(Configuration outConfig) {
2277        if (mAppToken != null && mAppToken.mFrozenMergedConfig.size() > 0) {
2278            outConfig.setTo(mAppToken.mFrozenMergedConfig.peek());
2279            return;
2280        }
2281        final Task task = getTask();
2282        final Configuration overrideConfig = task != null
2283                ? task.mOverrideConfig
2284                : Configuration.EMPTY;
2285        final Configuration serviceConfig = mService.mCurConfiguration;
2286        outConfig.setTo(serviceConfig);
2287        if (overrideConfig != Configuration.EMPTY) {
2288            outConfig.updateFrom(overrideConfig);
2289        }
2290    }
2291
2292    void reportResized() {
2293        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "wm.reportResized_" + getWindowTag());
2294        try {
2295            if (DEBUG_RESIZE || DEBUG_ORIENTATION) Slog.v(TAG, "Reporting new frame to " + this
2296                    + ": " + mCompatFrame);
2297            final Configuration newConfig = isConfigChanged() ? updateConfiguration() : null;
2298            if (DEBUG_ORIENTATION && mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING)
2299                Slog.i(TAG, "Resizing " + this + " WITH DRAW PENDING");
2300
2301            final Rect frame = mFrame;
2302            final Rect overscanInsets = mLastOverscanInsets;
2303            final Rect contentInsets = mLastContentInsets;
2304            final Rect visibleInsets = mLastVisibleInsets;
2305            final Rect stableInsets = mLastStableInsets;
2306            final Rect outsets = mLastOutsets;
2307            final boolean reportDraw = mWinAnimator.mDrawState == WindowStateAnimator.DRAW_PENDING;
2308            if (mAttrs.type != WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
2309                    && mClient instanceof IWindow.Stub) {
2310                // To prevent deadlock simulate one-way call if win.mClient is a local object.
2311                mService.mH.post(new Runnable() {
2312                    @Override
2313                    public void run() {
2314                        try {
2315                            dispatchResized(frame, overscanInsets, contentInsets, visibleInsets,
2316                                    stableInsets, outsets, reportDraw, newConfig);
2317                        } catch (RemoteException e) {
2318                            // Not a remote call, RemoteException won't be raised.
2319                        }
2320                    }
2321                });
2322            } else {
2323                dispatchResized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets,
2324                        outsets, reportDraw, newConfig);
2325            }
2326
2327            //TODO (multidisplay): Accessibility supported only for the default display.
2328            if (mService.mAccessibilityController != null
2329                    && getDisplayId() == Display.DEFAULT_DISPLAY) {
2330                mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
2331            }
2332
2333            mOverscanInsetsChanged = false;
2334            mContentInsetsChanged = false;
2335            mVisibleInsetsChanged = false;
2336            mStableInsetsChanged = false;
2337            mOutsetsChanged = false;
2338            mResizedWhileNotDragResizingReported = true;
2339            mWinAnimator.mSurfaceResized = false;
2340        } catch (RemoteException e) {
2341            mOrientationChanging = false;
2342            mLastFreezeDuration = (int)(SystemClock.elapsedRealtime()
2343                    - mService.mDisplayFreezeTime);
2344            // We are assuming the hosting process is dead or in a zombie state.
2345            Slog.w(TAG, "Failed to report 'resized' to the client of " + this
2346                    + ", removing this window.");
2347            mService.mPendingRemove.add(this);
2348            mService.mWindowPlacerLocked.requestTraversal();
2349        }
2350        Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2351    }
2352
2353    Rect getBackdropFrame(Rect frame) {
2354        // When the task is docked, we send fullscreen sized backDropFrame as soon as resizing
2355        // start even if we haven't received the relayout window, so that the client requests
2356        // the relayout sooner. When dragging stops, backDropFrame needs to stay fullscreen
2357        // until the window to small size, otherwise the multithread renderer will shift last
2358        // one or more frame to wrong offset. So here we send fullscreen backdrop if either
2359        // isDragResizing() or isDragResizeChanged() is true.
2360        boolean resizing = isDragResizing() || isDragResizeChanged();
2361        if (StackId.useWindowFrameForBackdrop(getStackId()) || !resizing) {
2362            return frame;
2363        }
2364        DisplayInfo displayInfo = getDisplayInfo();
2365        mTmpRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
2366        return mTmpRect;
2367    }
2368
2369    @Override
2370    public int getStackId() {
2371        final TaskStack stack = getStack();
2372        if (stack == null) {
2373            return INVALID_STACK_ID;
2374        }
2375        return stack.mStackId;
2376    }
2377
2378    private void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
2379            Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
2380            Configuration newConfig) throws RemoteException {
2381        final boolean forceRelayout = isDragResizeChanged() || mResizedWhileNotDragResizing;
2382
2383        mClient.resized(frame, overscanInsets, contentInsets, visibleInsets, stableInsets, outsets,
2384                reportDraw, newConfig, getBackdropFrame(frame),
2385                forceRelayout, mPolicy.isNavBarForcedShownLw(this));
2386        mDragResizingChangeReported = true;
2387    }
2388
2389    public void registerFocusObserver(IWindowFocusObserver observer) {
2390        synchronized(mService.mWindowMap) {
2391            if (mFocusCallbacks == null) {
2392                mFocusCallbacks = new RemoteCallbackList<IWindowFocusObserver>();
2393            }
2394            mFocusCallbacks.register(observer);
2395        }
2396    }
2397
2398    public void unregisterFocusObserver(IWindowFocusObserver observer) {
2399        synchronized(mService.mWindowMap) {
2400            if (mFocusCallbacks != null) {
2401                mFocusCallbacks.unregister(observer);
2402            }
2403        }
2404    }
2405
2406    public boolean isFocused() {
2407        synchronized(mService.mWindowMap) {
2408            return mService.mCurrentFocus == this;
2409        }
2410    }
2411
2412    boolean inFreeformWorkspace() {
2413        final Task task = getTask();
2414        return task != null && task.inFreeformWorkspace();
2415    }
2416
2417    @Override
2418    public boolean isInMultiWindowMode() {
2419        final Task task = getTask();
2420        return task != null && !task.isFullscreen();
2421    }
2422
2423    boolean isDragResizeChanged() {
2424        return mDragResizing != computeDragResizing();
2425    }
2426
2427    /**
2428     * @return Whether we reported a drag resize change to the application or not already.
2429     */
2430    boolean isDragResizingChangeReported() {
2431        return mDragResizingChangeReported;
2432    }
2433
2434    /**
2435     * Resets the state whether we reported a drag resize change to the app.
2436     */
2437    void resetDragResizingChangeReported() {
2438        mDragResizingChangeReported = false;
2439    }
2440
2441    /**
2442     * Set whether we got resized but drag resizing flag was false.
2443     * @see #isResizedWhileNotDragResizing().
2444     */
2445    void setResizedWhileNotDragResizing(boolean resizedWhileNotDragResizing) {
2446        mResizedWhileNotDragResizing = resizedWhileNotDragResizing;
2447        mResizedWhileNotDragResizingReported = !resizedWhileNotDragResizing;
2448    }
2449
2450    /**
2451     * Indicates whether we got resized but drag resizing flag was false. In this case, we also
2452     * need to recreate the surface and defer surface bound updates in order to make sure the
2453     * buffer contents and the positioning/size stay in sync.
2454     */
2455    boolean isResizedWhileNotDragResizing() {
2456        return mResizedWhileNotDragResizing;
2457    }
2458
2459    /**
2460     * @return Whether we reported "resize while not drag resizing" to the application.
2461     * @see #isResizedWhileNotDragResizing()
2462     */
2463    boolean isResizedWhileNotDragResizingReported() {
2464        return mResizedWhileNotDragResizingReported;
2465    }
2466
2467    int getResizeMode() {
2468        return mResizeMode;
2469    }
2470
2471    boolean computeDragResizing() {
2472        final Task task = getTask();
2473        if (task == null) {
2474            return false;
2475        }
2476        if (mAttrs.width != MATCH_PARENT || mAttrs.height != MATCH_PARENT) {
2477
2478            // Floating windows never enter drag resize mode.
2479            return false;
2480        }
2481        if (task.isDragResizing()) {
2482            return true;
2483        }
2484
2485        // If the bounds are currently frozen, it means that the layout size that the app sees
2486        // and the bounds we clip this window to might be different. In order to avoid holes, we
2487        // simulate that we are still resizing so the app fills the hole with the resizing
2488        // background.
2489        return (mDisplayContent.mDividerControllerLocked.isResizing()
2490                        || mAppToken != null && !mAppToken.mFrozenBounds.isEmpty()) &&
2491                !task.inFreeformWorkspace() && !isGoneForLayoutLw();
2492
2493    }
2494
2495    void setDragResizing() {
2496        final boolean resizing = computeDragResizing();
2497        if (resizing == mDragResizing) {
2498            return;
2499        }
2500        mDragResizing = resizing;
2501        final Task task = getTask();
2502        if (task != null && task.isDragResizing()) {
2503            mResizeMode = task.getDragResizeMode();
2504        } else {
2505            mResizeMode = mDragResizing && mDisplayContent.mDividerControllerLocked.isResizing()
2506                    ? DRAG_RESIZE_MODE_DOCKED_DIVIDER
2507                    : DRAG_RESIZE_MODE_FREEFORM;
2508        }
2509    }
2510
2511    boolean isDragResizing() {
2512        return mDragResizing;
2513    }
2514
2515    boolean isDockedResizing() {
2516        return mDragResizing && getResizeMode() == DRAG_RESIZE_MODE_DOCKED_DIVIDER;
2517    }
2518
2519    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2520        final TaskStack stack = getStack();
2521        pw.print(prefix); pw.print("mDisplayId="); pw.print(getDisplayId());
2522                if (stack != null) {
2523                    pw.print(" stackId="); pw.print(stack.mStackId);
2524                }
2525                if (mNotOnAppsDisplay) {
2526                    pw.print(" mNotOnAppsDisplay="); pw.print(mNotOnAppsDisplay);
2527                }
2528                pw.print(" mSession="); pw.print(mSession);
2529                pw.print(" mClient="); pw.println(mClient.asBinder());
2530        pw.print(prefix); pw.print("mOwnerUid="); pw.print(mOwnerUid);
2531                pw.print(" mShowToOwnerOnly="); pw.print(mShowToOwnerOnly);
2532                pw.print(" package="); pw.print(mAttrs.packageName);
2533                pw.print(" appop="); pw.println(AppOpsManager.opToName(mAppOp));
2534        pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
2535        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
2536                pw.print(" h="); pw.print(mRequestedHeight);
2537                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
2538        if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
2539            pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
2540                    pw.print(" h="); pw.println(mLastRequestedHeight);
2541        }
2542        if (isChildWindow() || mLayoutAttached) {
2543            pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
2544                    pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
2545        }
2546        if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
2547            pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
2548                    pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
2549                    pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
2550                    pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
2551        }
2552        if (dumpAll) {
2553            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
2554                    pw.print(" mSubLayer="); pw.print(mSubLayer);
2555                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
2556                    pw.print((mTargetAppToken != null ?
2557                            mTargetAppToken.mAppAnimator.animLayerAdjustment
2558                          : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0)));
2559                    pw.print("="); pw.print(mWinAnimator.mAnimLayer);
2560                    pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
2561        }
2562        if (dumpAll) {
2563            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
2564            pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
2565            if (mAppToken != null) {
2566                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
2567                pw.print(prefix); pw.print(" isAnimatingWithSavedSurface()=");
2568                pw.print(isAnimatingWithSavedSurface());
2569                pw.print(" mAppDied=");pw.println(mAppDied);
2570            }
2571            if (mTargetAppToken != null) {
2572                pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
2573            }
2574            pw.print(prefix); pw.print("mViewVisibility=0x");
2575            pw.print(Integer.toHexString(mViewVisibility));
2576            pw.print(" mHaveFrame="); pw.print(mHaveFrame);
2577            pw.print(" mObscured="); pw.println(mObscured);
2578            pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
2579            pw.print(" mSystemUiVisibility=0x");
2580            pw.println(Integer.toHexString(mSystemUiVisibility));
2581        }
2582        if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || !mAppOpVisibility
2583                || mAttachedHidden) {
2584            pw.print(prefix); pw.print("mPolicyVisibility=");
2585                    pw.print(mPolicyVisibility);
2586                    pw.print(" mPolicyVisibilityAfterAnim=");
2587                    pw.print(mPolicyVisibilityAfterAnim);
2588                    pw.print(" mAppOpVisibility=");
2589                    pw.print(mAppOpVisibility);
2590                    pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
2591        }
2592        if (!mRelayoutCalled || mLayoutNeeded) {
2593            pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
2594                    pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
2595        }
2596        if (mXOffset != 0 || mYOffset != 0) {
2597            pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
2598                    pw.print(" y="); pw.println(mYOffset);
2599        }
2600        if (dumpAll) {
2601            pw.print(prefix); pw.print("mGivenContentInsets=");
2602                    mGivenContentInsets.printShortString(pw);
2603                    pw.print(" mGivenVisibleInsets=");
2604                    mGivenVisibleInsets.printShortString(pw);
2605                    pw.println();
2606            if (mTouchableInsets != 0 || mGivenInsetsPending) {
2607                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
2608                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
2609                Region region = new Region();
2610                getTouchableRegion(region);
2611                pw.print(prefix); pw.print("touchable region="); pw.println(region);
2612            }
2613            pw.print(prefix); pw.print("mMergedConfiguration="); pw.println(mMergedConfiguration);
2614        }
2615        pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
2616                pw.print(" mShownPosition="); mShownPosition.printShortString(pw);
2617                pw.print(" isReadyForDisplay()="); pw.print(isReadyForDisplay());
2618                pw.print(" hasSavedSurface()="); pw.print(hasSavedSurface());
2619                pw.print(" mWindowRemovalAllowed="); pw.println(mWindowRemovalAllowed);
2620        if (dumpAll) {
2621            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
2622                    pw.print(" last="); mLastFrame.printShortString(pw);
2623                    pw.println();
2624        }
2625        if (mEnforceSizeCompat) {
2626            pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
2627                    pw.println();
2628        }
2629        if (dumpAll) {
2630            pw.print(prefix); pw.print("Frames: containing=");
2631                    mContainingFrame.printShortString(pw);
2632                    pw.print(" parent="); mParentFrame.printShortString(pw);
2633                    pw.println();
2634            pw.print(prefix); pw.print("    display="); mDisplayFrame.printShortString(pw);
2635                    pw.print(" overscan="); mOverscanFrame.printShortString(pw);
2636                    pw.println();
2637            pw.print(prefix); pw.print("    content="); mContentFrame.printShortString(pw);
2638                    pw.print(" visible="); mVisibleFrame.printShortString(pw);
2639                    pw.println();
2640            pw.print(prefix); pw.print("    decor="); mDecorFrame.printShortString(pw);
2641                    pw.println();
2642            pw.print(prefix); pw.print("    outset="); mOutsetFrame.printShortString(pw);
2643                    pw.println();
2644            pw.print(prefix); pw.print("Cur insets: overscan=");
2645                    mOverscanInsets.printShortString(pw);
2646                    pw.print(" content="); mContentInsets.printShortString(pw);
2647                    pw.print(" visible="); mVisibleInsets.printShortString(pw);
2648                    pw.print(" stable="); mStableInsets.printShortString(pw);
2649                    pw.print(" surface="); mAttrs.surfaceInsets.printShortString(pw);
2650                    pw.print(" outsets="); mOutsets.printShortString(pw);
2651                    pw.println();
2652            pw.print(prefix); pw.print("Lst insets: overscan=");
2653                    mLastOverscanInsets.printShortString(pw);
2654                    pw.print(" content="); mLastContentInsets.printShortString(pw);
2655                    pw.print(" visible="); mLastVisibleInsets.printShortString(pw);
2656                    pw.print(" stable="); mLastStableInsets.printShortString(pw);
2657                    pw.print(" physical="); mLastOutsets.printShortString(pw);
2658                    pw.print(" outset="); mLastOutsets.printShortString(pw);
2659                    pw.println();
2660        }
2661        pw.print(prefix); pw.print(mWinAnimator); pw.println(":");
2662        mWinAnimator.dump(pw, prefix + "  ", dumpAll);
2663        if (mAnimatingExit || mRemoveOnExit || mDestroying || mRemoved) {
2664            pw.print(prefix); pw.print("mAnimatingExit="); pw.print(mAnimatingExit);
2665                    pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
2666                    pw.print(" mDestroying="); pw.print(mDestroying);
2667                    pw.print(" mRemoved="); pw.println(mRemoved);
2668        }
2669        if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
2670            pw.print(prefix); pw.print("mOrientationChanging=");
2671                    pw.print(mOrientationChanging);
2672                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
2673                    pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
2674        }
2675        if (mLastFreezeDuration != 0) {
2676            pw.print(prefix); pw.print("mLastFreezeDuration=");
2677                    TimeUtils.formatDuration(mLastFreezeDuration, pw); pw.println();
2678        }
2679        if (mHScale != 1 || mVScale != 1) {
2680            pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
2681                    pw.print(" mVScale="); pw.println(mVScale);
2682        }
2683        if (mWallpaperX != -1 || mWallpaperY != -1) {
2684            pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
2685                    pw.print(" mWallpaperY="); pw.println(mWallpaperY);
2686        }
2687        if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
2688            pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
2689                    pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
2690        }
2691        if (mWallpaperDisplayOffsetX != Integer.MIN_VALUE
2692                || mWallpaperDisplayOffsetY != Integer.MIN_VALUE) {
2693            pw.print(prefix); pw.print("mWallpaperDisplayOffsetX=");
2694                    pw.print(mWallpaperDisplayOffsetX);
2695                    pw.print(" mWallpaperDisplayOffsetY=");
2696                    pw.println(mWallpaperDisplayOffsetY);
2697        }
2698        if (mDrawLock != null) {
2699            pw.print(prefix); pw.println("mDrawLock=" + mDrawLock);
2700        }
2701        if (isDragResizing()) {
2702            pw.print(prefix); pw.println("isDragResizing=" + isDragResizing());
2703        }
2704        if (computeDragResizing()) {
2705            pw.print(prefix); pw.println("computeDragResizing=" + computeDragResizing());
2706        }
2707    }
2708
2709    String makeInputChannelName() {
2710        return Integer.toHexString(System.identityHashCode(this))
2711            + " " + getWindowTag();
2712    }
2713
2714    CharSequence getWindowTag() {
2715        CharSequence tag = mAttrs.getTitle();
2716        if (tag == null || tag.length() <= 0) {
2717            tag = mAttrs.packageName;
2718        }
2719        return tag;
2720    }
2721
2722    @Override
2723    public String toString() {
2724        final CharSequence title = getWindowTag();
2725        if (mStringNameCache == null || mLastTitle != title || mWasExiting != mAnimatingExit) {
2726            mLastTitle = title;
2727            mWasExiting = mAnimatingExit;
2728            mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
2729                    + " u" + UserHandle.getUserId(mSession.mUid)
2730                    + " " + mLastTitle + (mAnimatingExit ? " EXITING}" : "}");
2731        }
2732        return mStringNameCache;
2733    }
2734
2735    void transformClipRectFromScreenToSurfaceSpace(Rect clipRect) {
2736         if (mHScale >= 0) {
2737            clipRect.left = (int) (clipRect.left / mHScale);
2738            clipRect.right = (int) Math.ceil(clipRect.right / mHScale);
2739        }
2740        if (mVScale >= 0) {
2741            clipRect.top = (int) (clipRect.top / mVScale);
2742            clipRect.bottom = (int) Math.ceil(clipRect.bottom / mVScale);
2743        }
2744    }
2745
2746    void applyGravityAndUpdateFrame(Rect containingFrame, Rect displayFrame) {
2747        final int pw = containingFrame.width();
2748        final int ph = containingFrame.height();
2749        final Task task = getTask();
2750        final boolean nonFullscreenTask = isInMultiWindowMode();
2751        final boolean noLimits = (mAttrs.flags & FLAG_LAYOUT_NO_LIMITS) != 0;
2752
2753        // We need to fit it to the display if either
2754        // a) The task is fullscreen, or we don't have a task (we assume fullscreen for the taskless
2755        // windows)
2756        // b) If it's a child window, we also need to fit it to the display unless
2757        // FLAG_LAYOUT_NO_LIMITS is set. This is so we place Popup and similar windows on screen,
2758        // but SurfaceViews want to be always at a specific location so we don't fit it to the
2759        // display.
2760        final boolean fitToDisplay = (task == null || !nonFullscreenTask)
2761                || (isChildWindow() && !noLimits);
2762        float x, y;
2763        int w,h;
2764
2765        if ((mAttrs.flags & FLAG_SCALED) != 0) {
2766            if (mAttrs.width < 0) {
2767                w = pw;
2768            } else if (mEnforceSizeCompat) {
2769                w = (int)(mAttrs.width * mGlobalScale + .5f);
2770            } else {
2771                w = mAttrs.width;
2772            }
2773            if (mAttrs.height < 0) {
2774                h = ph;
2775            } else if (mEnforceSizeCompat) {
2776                h = (int)(mAttrs.height * mGlobalScale + .5f);
2777            } else {
2778                h = mAttrs.height;
2779            }
2780        } else {
2781            if (mAttrs.width == MATCH_PARENT) {
2782                w = pw;
2783            } else if (mEnforceSizeCompat) {
2784                w = (int)(mRequestedWidth * mGlobalScale + .5f);
2785            } else {
2786                w = mRequestedWidth;
2787            }
2788            if (mAttrs.height == MATCH_PARENT) {
2789                h = ph;
2790            } else if (mEnforceSizeCompat) {
2791                h = (int)(mRequestedHeight * mGlobalScale + .5f);
2792            } else {
2793                h = mRequestedHeight;
2794            }
2795        }
2796
2797        if (mEnforceSizeCompat) {
2798            x = mAttrs.x * mGlobalScale;
2799            y = mAttrs.y * mGlobalScale;
2800        } else {
2801            x = mAttrs.x;
2802            y = mAttrs.y;
2803        }
2804
2805        if (nonFullscreenTask && !layoutInParentFrame()) {
2806            // Make sure window fits in containing frame since it is in a non-fullscreen task as
2807            // required by {@link Gravity#apply} call.
2808            w = Math.min(w, pw);
2809            h = Math.min(h, ph);
2810        }
2811
2812        // Set mFrame
2813        Gravity.apply(mAttrs.gravity, w, h, containingFrame,
2814                (int) (x + mAttrs.horizontalMargin * pw),
2815                (int) (y + mAttrs.verticalMargin * ph), mFrame);
2816
2817        // Now make sure the window fits in the overall display frame.
2818        if (fitToDisplay) {
2819            Gravity.applyDisplay(mAttrs.gravity, displayFrame, mFrame);
2820        }
2821
2822        // We need to make sure we update the CompatFrame as it is used for
2823        // cropping decisions, etc, on systems where we lack a decor layer.
2824        mCompatFrame.set(mFrame);
2825        if (mEnforceSizeCompat) {
2826            // See comparable block in computeFrameLw.
2827            mCompatFrame.scale(mInvGlobalScale);
2828        }
2829    }
2830
2831    boolean isChildWindow() {
2832        return mAttachedWindow != null;
2833    }
2834
2835    boolean layoutInParentFrame() {
2836        return isChildWindow() && (mAttrs.privateFlags & PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME) != 0;
2837    }
2838
2839    void setReplacing(boolean animate) {
2840        if ((mAttrs.privateFlags & PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH) != 0
2841                || mAttrs.type == TYPE_APPLICATION_STARTING) {
2842            // We don't set replacing on starting windows since they are added by window manager and
2843            // not the client so won't be replaced by the client.
2844            return;
2845        }
2846
2847        mWillReplaceWindow = true;
2848        mReplacingWindow = null;
2849        mAnimateReplacingWindow = animate;
2850    }
2851
2852    void resetReplacing() {
2853        mWillReplaceWindow = false;
2854        mReplacingWindow = null;
2855        mAnimateReplacingWindow = false;
2856    }
2857
2858    void requestUpdateWallpaperIfNeeded() {
2859        if (mDisplayContent != null && (mAttrs.flags & FLAG_SHOW_WALLPAPER) != 0) {
2860            mDisplayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2861            mDisplayContent.layoutNeeded = true;
2862            mService.mWindowPlacerLocked.requestTraversal();
2863        }
2864    }
2865
2866    float translateToWindowX(float x) {
2867        float winX = x - mFrame.left;
2868        if (mEnforceSizeCompat) {
2869            winX *= mGlobalScale;
2870        }
2871        return winX;
2872    }
2873
2874    float translateToWindowY(float y) {
2875        float winY = y - mFrame.top;
2876        if (mEnforceSizeCompat) {
2877            winY *= mGlobalScale;
2878        }
2879        return winY;
2880    }
2881
2882    void transferDimToReplacement() {
2883        final DimLayer.DimLayerUser dimLayerUser = getDimLayerUser();
2884        if (dimLayerUser != null && mDisplayContent != null) {
2885            mDisplayContent.mDimLayerController.applyDim(dimLayerUser,
2886                    mReplacingWindow.mWinAnimator,
2887                    (mAttrs.flags & FLAG_DIM_BEHIND) != 0 ? true : false);
2888        }
2889    }
2890
2891    // During activity relaunch due to resize, we sometimes use window replacement
2892    // for only child windows (as the main window is handled by window preservation)
2893    // and the big surface.
2894    //
2895    // Though windows of TYPE_APPLICATION (as opposed to TYPE_BASE_APPLICATION)
2896    // are not children in the sense of an attached window, we also want to replace
2897    // them at such phases, as they won't be covered by window preservation,
2898    // and in general we expect them to return following relaunch.
2899    boolean shouldBeReplacedWithChildren() {
2900        return isChildWindow() || mAttrs.type == TYPE_APPLICATION;
2901    }
2902}
2903