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