WindowState.java revision 59c009776dae5ccbdfb93d7151ff2065ca049dc3
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 static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
20import static android.view.WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
21import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
22import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
23import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
24import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
25
26import com.android.server.input.InputWindowHandle;
27
28import android.content.Context;
29import android.content.res.Configuration;
30import android.graphics.Matrix;
31import android.graphics.PixelFormat;
32import android.graphics.Rect;
33import android.graphics.RectF;
34import android.graphics.Region;
35import android.os.IBinder;
36import android.os.RemoteException;
37import android.util.Slog;
38import android.view.DisplayInfo;
39import android.view.Gravity;
40import android.view.IApplicationToken;
41import android.view.IWindow;
42import android.view.InputChannel;
43import android.view.View;
44import android.view.ViewTreeObserver;
45import android.view.WindowManager;
46import android.view.WindowManagerPolicy;
47
48import java.io.PrintWriter;
49import java.util.ArrayList;
50
51class WindowList extends ArrayList<WindowState> {
52}
53
54/**
55 * A window in the window manager.
56 */
57final class WindowState implements WindowManagerPolicy.WindowState {
58    static final String TAG = "WindowState";
59
60    static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
61    static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
62    static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
63    static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC;
64
65    final WindowManagerService mService;
66    final WindowManagerPolicy mPolicy;
67    final Context mContext;
68    final Session mSession;
69    final IWindow mClient;
70    WindowToken mToken;
71    WindowToken mRootToken;
72    AppWindowToken mAppToken;
73    AppWindowToken mTargetAppToken;
74
75    // mAttrs.flags is tested in animation without being locked. If the bits tested are ever
76    // modified they will need to be locked.
77    final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
78    final DeathRecipient mDeathRecipient;
79    final WindowState mAttachedWindow;
80    final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
81    final int mBaseLayer;
82    final int mSubLayer;
83    final boolean mLayoutAttached;
84    final boolean mIsImWindow;
85    final boolean mIsWallpaper;
86    final boolean mIsFloatingLayer;
87    int mSeq;
88    boolean mEnforceSizeCompat;
89    int mViewVisibility;
90    int mSystemUiVisibility;
91    boolean mPolicyVisibility = true;
92    boolean mPolicyVisibilityAfterAnim = true;
93    boolean mAppFreezing;
94    boolean mAttachedHidden;    // is our parent window hidden?
95    boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
96
97    /**
98     * The window size that was requested by the application.  These are in
99     * the application's coordinate space (without compatibility scale applied).
100     */
101    int mRequestedWidth;
102    int mRequestedHeight;
103    int mLastRequestedWidth;
104    int mLastRequestedHeight;
105
106    int mLayer;
107    boolean mHaveFrame;
108    boolean mObscured;
109    boolean mTurnOnScreen;
110
111    int mLayoutSeq = -1;
112
113    Configuration mConfiguration = null;
114
115    /**
116     * Actual frame shown on-screen (may be modified by animation).  These
117     * are in the screen's coordinate space (WITH the compatibility scale
118     * applied).
119     */
120    final RectF mShownFrame = new RectF();
121
122    /**
123     * Insets that determine the actually visible area.  These are in the application's
124     * coordinate space (without compatibility scale applied).
125     */
126    final Rect mVisibleInsets = new Rect();
127    final Rect mLastVisibleInsets = new Rect();
128    boolean mVisibleInsetsChanged;
129
130    /**
131     * Insets that are covered by system windows (such as the status bar) and
132     * transient docking windows (such as the IME).  These are in the application's
133     * coordinate space (without compatibility scale applied).
134     */
135    final Rect mContentInsets = new Rect();
136    final Rect mLastContentInsets = new Rect();
137    boolean mContentInsetsChanged;
138
139    /**
140     * Set to true if we are waiting for this window to receive its
141     * given internal insets before laying out other windows based on it.
142     */
143    boolean mGivenInsetsPending;
144
145    /**
146     * These are the content insets that were given during layout for
147     * this window, to be applied to windows behind it.
148     */
149    final Rect mGivenContentInsets = new Rect();
150
151    /**
152     * These are the visible insets that were given during layout for
153     * this window, to be applied to windows behind it.
154     */
155    final Rect mGivenVisibleInsets = new Rect();
156
157    /**
158     * This is the given touchable area relative to the window frame, or null if none.
159     */
160    final Region mGivenTouchableRegion = new Region();
161
162    /**
163     * Flag indicating whether the touchable region should be adjusted by
164     * the visible insets; if false the area outside the visible insets is
165     * NOT touchable, so we must use those to adjust the frame during hit
166     * tests.
167     */
168    int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
169
170    /**
171     * This is rectangle of the window's surface that is not covered by
172     * system decorations.
173     */
174    final Rect mSystemDecorRect = new Rect();
175    final Rect mLastSystemDecorRect = new Rect();
176
177    // Current transformation being applied.
178    float mGlobalScale=1;
179    float mInvGlobalScale=1;
180    float mHScale=1, mVScale=1;
181    float mLastHScale=1, mLastVScale=1;
182    final Matrix mTmpMatrix = new Matrix();
183
184    // "Real" frame that the application sees, in display coordinate space.
185    final Rect mFrame = new Rect();
186    final Rect mLastFrame = new Rect();
187    // Frame that is scaled to the application's coordinate space when in
188    // screen size compatibility mode.
189    final Rect mCompatFrame = new Rect();
190
191    final Rect mContainingFrame = new Rect();
192    final Rect mDisplayFrame = new Rect();
193    final Rect mContentFrame = new Rect();
194    final Rect mParentFrame = new Rect();
195    final Rect mVisibleFrame = new Rect();
196
197    boolean mContentChanged;
198
199    // If a window showing a wallpaper: the requested offset for the
200    // wallpaper; if a wallpaper window: the currently applied offset.
201    float mWallpaperX = -1;
202    float mWallpaperY = -1;
203
204    // If a window showing a wallpaper: what fraction of the offset
205    // range corresponds to a full virtual screen.
206    float mWallpaperXStep = -1;
207    float mWallpaperYStep = -1;
208
209    // Wallpaper windows: pixels offset based on above variables.
210    int mXOffset;
211    int mYOffset;
212
213    // This is set after IWindowSession.relayout() has been called at
214    // least once for the window.  It allows us to detect the situation
215    // where we don't yet have a surface, but should have one soon, so
216    // we can give the window focus before waiting for the relayout.
217    boolean mRelayoutCalled;
218
219    // If the application has called relayout() with changes that can
220    // impact its window's size, we need to perform a layout pass on it
221    // even if it is not currently visible for layout.  This is set
222    // when in that case until the layout is done.
223    boolean mLayoutNeeded;
224
225    // Currently running an exit animation?
226    boolean mExiting;
227
228    // Currently on the mDestroySurface list?
229    boolean mDestroying;
230
231    // Completely remove from window manager after exit animation?
232    boolean mRemoveOnExit;
233
234    // Set when the orientation is changing and this window has not yet
235    // been updated for the new orientation.
236    boolean mOrientationChanging;
237
238    // Is this window now (or just being) removed?
239    boolean mRemoved;
240
241    // Temp for keeping track of windows that have been removed when
242    // rebuilding window list.
243    boolean mRebuilding;
244
245    // Input channel and input window handle used by the input dispatcher.
246    final InputWindowHandle mInputWindowHandle;
247    InputChannel mInputChannel;
248
249    // Used to improve performance of toString()
250    String mStringNameCache;
251    CharSequence mLastTitle;
252    boolean mWasPaused;
253
254    final WindowStateAnimator mWinAnimator;
255
256    boolean mHasSurface = false;
257
258    DisplayContent  mDisplayContent;
259
260    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
261           WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
262           int viewVisibility, final DisplayContent displayContent) {
263        mService = service;
264        mSession = s;
265        mClient = c;
266        mToken = token;
267        mAttrs.copyFrom(a);
268        mViewVisibility = viewVisibility;
269        mDisplayContent = displayContent;
270        mPolicy = mService.mPolicy;
271        mContext = mService.mContext;
272        DeathRecipient deathRecipient = new DeathRecipient();
273        mSeq = seq;
274        mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
275        if (WindowManagerService.localLOGV) Slog.v(
276            TAG, "Window " + this + " client=" + c.asBinder()
277            + " token=" + token + " (" + mAttrs.token + ")");
278        try {
279            c.asBinder().linkToDeath(deathRecipient, 0);
280        } catch (RemoteException e) {
281            mDeathRecipient = null;
282            mAttachedWindow = null;
283            mLayoutAttached = false;
284            mIsImWindow = false;
285            mIsWallpaper = false;
286            mIsFloatingLayer = false;
287            mBaseLayer = 0;
288            mSubLayer = 0;
289            mInputWindowHandle = null;
290            mWinAnimator = null;
291            return;
292        }
293        mDeathRecipient = deathRecipient;
294
295        if ((mAttrs.type >= FIRST_SUB_WINDOW &&
296                mAttrs.type <= LAST_SUB_WINDOW)) {
297            // The multiplier here is to reserve space for multiple
298            // windows in the same type layer.
299            mBaseLayer = mPolicy.windowTypeToLayerLw(
300                    attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
301                    + WindowManagerService.TYPE_LAYER_OFFSET;
302            mSubLayer = mPolicy.subWindowTypeToLayerLw(a.type);
303            mAttachedWindow = attachedWindow;
304            if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Adding " + this + " to " + mAttachedWindow);
305            mAttachedWindow.mChildWindows.add(this);
306            mLayoutAttached = mAttrs.type !=
307                    WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
308            mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
309                    || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
310            mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
311            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
312        } else {
313            // The multiplier here is to reserve space for multiple
314            // windows in the same type layer.
315            mBaseLayer = mPolicy.windowTypeToLayerLw(a.type)
316                    * WindowManagerService.TYPE_LAYER_MULTIPLIER
317                    + WindowManagerService.TYPE_LAYER_OFFSET;
318            mSubLayer = 0;
319            mAttachedWindow = null;
320            mLayoutAttached = false;
321            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
322                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
323            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
324            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
325        }
326
327        WindowState appWin = this;
328        while (appWin.mAttachedWindow != null) {
329            appWin = appWin.mAttachedWindow;
330        }
331        WindowToken appToken = appWin.mToken;
332        while (appToken.appWindowToken == null) {
333            WindowToken parent = mService.mTokenMap.get(appToken.token);
334            if (parent == null || appToken == parent) {
335                break;
336            }
337            appToken = parent;
338        }
339        mRootToken = appToken;
340        mAppToken = appToken.appWindowToken;
341
342        mWinAnimator = new WindowStateAnimator(this);
343        mWinAnimator.mAlpha = a.alpha;
344
345        mRequestedWidth = 0;
346        mRequestedHeight = 0;
347        mLastRequestedWidth = 0;
348        mLastRequestedHeight = 0;
349        mXOffset = 0;
350        mYOffset = 0;
351        mLayer = 0;
352        mInputWindowHandle = new InputWindowHandle(
353                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this,
354                displayContent.getDisplayId());
355    }
356
357    void attach() {
358        if (WindowManagerService.localLOGV) Slog.v(
359            TAG, "Attaching " + this + " token=" + mToken
360            + ", list=" + mToken.windows);
361        mSession.windowAddedLocked();
362    }
363
364    @Override
365    public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
366        mHaveFrame = true;
367
368        final Rect container = mContainingFrame;
369        container.set(pf);
370
371        final Rect display = mDisplayFrame;
372        display.set(df);
373
374        final int pw = container.right - container.left;
375        final int ph = container.bottom - container.top;
376
377        int w,h;
378        if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) {
379            if (mAttrs.width < 0) {
380                w = pw;
381            } else if (mEnforceSizeCompat) {
382                w = (int)(mAttrs.width * mGlobalScale + .5f);
383            } else {
384                w = mAttrs.width;
385            }
386            if (mAttrs.height < 0) {
387                h = ph;
388            } else if (mEnforceSizeCompat) {
389                h = (int)(mAttrs.height * mGlobalScale + .5f);
390            } else {
391                h = mAttrs.height;
392            }
393        } else {
394            if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) {
395                w = pw;
396            } else if (mEnforceSizeCompat) {
397                w = (int)(mRequestedWidth * mGlobalScale + .5f);
398            } else {
399                w = mRequestedWidth;
400            }
401            if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
402                h = ph;
403            } else if (mEnforceSizeCompat) {
404                h = (int)(mRequestedHeight * mGlobalScale + .5f);
405            } else {
406                h = mRequestedHeight;
407            }
408        }
409
410        if (!mParentFrame.equals(pf)) {
411            //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
412            //        + " to " + pf);
413            mParentFrame.set(pf);
414            mContentChanged = true;
415        }
416        if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
417            mLastRequestedWidth = mRequestedWidth;
418            mLastRequestedHeight = mRequestedHeight;
419            mContentChanged = true;
420        }
421
422        final Rect content = mContentFrame;
423        content.set(cf);
424
425        final Rect visible = mVisibleFrame;
426        visible.set(vf);
427
428        final Rect frame = mFrame;
429        final int fw = frame.width();
430        final int fh = frame.height();
431
432        //System.out.println("In: w=" + w + " h=" + h + " container=" +
433        //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
434
435        float x, y;
436        if (mEnforceSizeCompat) {
437            x = mAttrs.x * mGlobalScale;
438            y = mAttrs.y * mGlobalScale;
439        } else {
440            x = mAttrs.x;
441            y = mAttrs.y;
442        }
443
444        Gravity.apply(mAttrs.gravity, w, h, container,
445                (int) (x + mAttrs.horizontalMargin * pw),
446                (int) (y + mAttrs.verticalMargin * ph), frame);
447
448        //System.out.println("Out: " + mFrame);
449
450        // Now make sure the window fits in the overall display.
451        Gravity.applyDisplay(mAttrs.gravity, df, frame);
452
453        // Make sure the system, content and visible frames are inside of the
454        // final window frame.
455        if (content.left < frame.left) content.left = frame.left;
456        if (content.top < frame.top) content.top = frame.top;
457        if (content.right > frame.right) content.right = frame.right;
458        if (content.bottom > frame.bottom) content.bottom = frame.bottom;
459        if (visible.left < frame.left) visible.left = frame.left;
460        if (visible.top < frame.top) visible.top = frame.top;
461        if (visible.right > frame.right) visible.right = frame.right;
462        if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
463
464        final Rect contentInsets = mContentInsets;
465        contentInsets.left = content.left-frame.left;
466        contentInsets.top = content.top-frame.top;
467        contentInsets.right = frame.right-content.right;
468        contentInsets.bottom = frame.bottom-content.bottom;
469
470        final Rect visibleInsets = mVisibleInsets;
471        visibleInsets.left = visible.left-frame.left;
472        visibleInsets.top = visible.top-frame.top;
473        visibleInsets.right = frame.right-visible.right;
474        visibleInsets.bottom = frame.bottom-visible.bottom;
475
476        mCompatFrame.set(frame);
477        if (mEnforceSizeCompat) {
478            // If there is a size compatibility scale being applied to the
479            // window, we need to apply this to its insets so that they are
480            // reported to the app in its coordinate space.
481            contentInsets.scale(mInvGlobalScale);
482            visibleInsets.scale(mInvGlobalScale);
483
484            // Also the scaled frame that we report to the app needs to be
485            // adjusted to be in its coordinate space.
486            mCompatFrame.scale(mInvGlobalScale);
487        }
488
489        if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
490            final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
491            mService.updateWallpaperOffsetLocked(this, displayInfo.appWidth, displayInfo.appHeight,
492                    false);
493        }
494
495        if (WindowManagerService.localLOGV) {
496            //if ("com.google.android.youtube".equals(mAttrs.packageName)
497            //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
498                Slog.v(TAG, "Resolving (mRequestedWidth="
499                        + mRequestedWidth + ", mRequestedheight="
500                        + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
501                        + "): frame=" + mFrame.toShortString()
502                        + " ci=" + contentInsets.toShortString()
503                        + " vi=" + visibleInsets.toShortString());
504            //}
505        }
506    }
507
508    @Override
509    public Rect getFrameLw() {
510        return mFrame;
511    }
512
513    @Override
514    public RectF getShownFrameLw() {
515        return mShownFrame;
516    }
517
518    @Override
519    public Rect getDisplayFrameLw() {
520        return mDisplayFrame;
521    }
522
523    @Override
524    public Rect getContentFrameLw() {
525        return mContentFrame;
526    }
527
528    @Override
529    public Rect getVisibleFrameLw() {
530        return mVisibleFrame;
531    }
532
533    @Override
534    public boolean getGivenInsetsPendingLw() {
535        return mGivenInsetsPending;
536    }
537
538    @Override
539    public Rect getGivenContentInsetsLw() {
540        return mGivenContentInsets;
541    }
542
543    @Override
544    public Rect getGivenVisibleInsetsLw() {
545        return mGivenVisibleInsets;
546    }
547
548    @Override
549    public WindowManager.LayoutParams getAttrs() {
550        return mAttrs;
551    }
552
553    public boolean getNeedsMenuLw(WindowManagerPolicy.WindowState bottom) {
554        int index = -1;
555        WindowState ws = this;
556        WindowList windows = getWindowList();
557        while (true) {
558            if ((ws.mAttrs.privateFlags
559                    & WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY) != 0) {
560                return (ws.mAttrs.flags & WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY) != 0;
561            }
562            // If we reached the bottom of the range of windows we are considering,
563            // assume no menu is needed.
564            if (ws == bottom) {
565                return false;
566            }
567            // The current window hasn't specified whether menu key is needed;
568            // look behind it.
569            // First, we may need to determine the starting position.
570            if (index < 0) {
571                index = windows.indexOf(ws);
572            }
573            index--;
574            if (index < 0) {
575                return false;
576            }
577            ws = windows.get(index);
578        }
579    }
580
581    public int getSystemUiVisibility() {
582        return mSystemUiVisibility;
583    }
584
585    public int getSurfaceLayer() {
586        return mLayer;
587    }
588
589    public IApplicationToken getAppToken() {
590        return mAppToken != null ? mAppToken.appToken : null;
591    }
592
593    public long getInputDispatchingTimeoutNanos() {
594        return mAppToken != null
595                ? mAppToken.inputDispatchingTimeoutNanos
596                : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
597    }
598
599    public boolean hasAppShownWindows() {
600        return mAppToken != null && (mAppToken.firstWindowDrawn || mAppToken.startingDisplayed);
601    }
602
603    boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
604        if (dsdx < .99999f || dsdx > 1.00001f) return false;
605        if (dtdy < .99999f || dtdy > 1.00001f) return false;
606        if (dtdx < -.000001f || dtdx > .000001f) return false;
607        if (dsdy < -.000001f || dsdy > .000001f) return false;
608        return true;
609    }
610
611    void prelayout() {
612        if (mEnforceSizeCompat) {
613            mGlobalScale = mService.mCompatibleScreenScale;
614            mInvGlobalScale = 1/mGlobalScale;
615        } else {
616            mGlobalScale = mInvGlobalScale = 1;
617        }
618    }
619
620    /**
621     * Is this window visible?  It is not visible if there is no
622     * surface, or we are in the process of running an exit animation
623     * that will remove the surface, or its app token has been hidden.
624     */
625    public boolean isVisibleLw() {
626        final AppWindowToken atoken = mAppToken;
627        return mHasSurface && mPolicyVisibility && !mAttachedHidden
628                && (atoken == null || !atoken.hiddenRequested)
629                && !mExiting && !mDestroying;
630    }
631
632    /**
633     * Like {@link #isVisibleLw}, but also counts a window that is currently
634     * "hidden" behind the keyguard as visible.  This allows us to apply
635     * things like window flags that impact the keyguard.
636     * XXX I am starting to think we need to have ANOTHER visibility flag
637     * for this "hidden behind keyguard" state rather than overloading
638     * mPolicyVisibility.  Ungh.
639     */
640    public boolean isVisibleOrBehindKeyguardLw() {
641        if (mRootToken.waitingToShow &&
642                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
643            return false;
644        }
645        final AppWindowToken atoken = mAppToken;
646        final boolean animating = atoken != null
647                ? (atoken.mAppAnimator.animation != null) : false;
648        return mHasSurface && !mDestroying && !mExiting
649                && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
650                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
651                                && !mRootToken.hidden)
652                        || mWinAnimator.mAnimation != null || animating);
653    }
654
655    /**
656     * Is this window visible, ignoring its app token?  It is not visible
657     * if there is no surface, or we are in the process of running an exit animation
658     * that will remove the surface.
659     */
660    public boolean isWinVisibleLw() {
661        final AppWindowToken atoken = mAppToken;
662        return mHasSurface && mPolicyVisibility && !mAttachedHidden
663                && (atoken == null || !atoken.hiddenRequested || atoken.mAppAnimator.animating)
664                && !mExiting && !mDestroying;
665    }
666
667    /**
668     * The same as isVisible(), but follows the current hidden state of
669     * the associated app token, not the pending requested hidden state.
670     */
671    boolean isVisibleNow() {
672        return mHasSurface && mPolicyVisibility && !mAttachedHidden
673                && !mRootToken.hidden && !mExiting && !mDestroying;
674    }
675
676    /**
677     * Can this window possibly be a drag/drop target?  The test here is
678     * a combination of the above "visible now" with the check that the
679     * Input Manager uses when discarding windows from input consideration.
680     */
681    boolean isPotentialDragTarget() {
682        return isVisibleNow() && !mRemoved
683                && mInputChannel != null && mInputWindowHandle != null;
684    }
685
686    /**
687     * Same as isVisible(), but we also count it as visible between the
688     * call to IWindowSession.add() and the first relayout().
689     */
690    boolean isVisibleOrAdding() {
691        final AppWindowToken atoken = mAppToken;
692        return (mHasSurface || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
693                && mPolicyVisibility && !mAttachedHidden
694                && (atoken == null || !atoken.hiddenRequested)
695                && !mExiting && !mDestroying;
696    }
697
698    /**
699     * Is this window currently on-screen?  It is on-screen either if it
700     * is visible or it is currently running an animation before no longer
701     * being visible.
702     */
703    boolean isOnScreen() {
704        if (!mHasSurface || !mPolicyVisibility || mDestroying) {
705            return false;
706        }
707        final AppWindowToken atoken = mAppToken;
708        if (atoken != null) {
709            return ((!mAttachedHidden && !atoken.hiddenRequested)
710                            || mWinAnimator.mAnimation != null || atoken.mAppAnimator.animation != null);
711        }
712        return !mAttachedHidden || mWinAnimator.mAnimation != null;
713    }
714
715    /**
716     * Like isOnScreen(), but we don't return true if the window is part
717     * of a transition that has not yet been started.
718     */
719    boolean isReadyForDisplay() {
720        if (mRootToken.waitingToShow &&
721                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
722            return false;
723        }
724        return mHasSurface && mPolicyVisibility && !mDestroying
725                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
726                                && !mRootToken.hidden)
727                        || mWinAnimator.mAnimation != null
728                        || ((mAppToken != null) && (mAppToken.mAppAnimator.animation != null)));
729    }
730
731    /**
732     * Like isReadyForDisplay(), but ignores any force hiding of the window due
733     * to the keyguard.
734     */
735    boolean isReadyForDisplayIgnoringKeyguard() {
736        if (mRootToken.waitingToShow &&
737                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
738            return false;
739        }
740        final AppWindowToken atoken = mAppToken;
741        if (atoken == null && !mPolicyVisibility) {
742            // If this is not an app window, and the policy has asked to force
743            // hide, then we really do want to hide.
744            return false;
745        }
746        return mHasSurface && !mDestroying
747                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
748                                && !mRootToken.hidden)
749                        || mWinAnimator.mAnimation != null
750                        || ((atoken != null) && (atoken.mAppAnimator.animation != null)
751                                && !mWinAnimator.isDummyAnimation()));
752    }
753
754    /**
755     * Like isOnScreen, but returns false if the surface hasn't yet
756     * been drawn.
757     */
758    public boolean isDisplayedLw() {
759        final AppWindowToken atoken = mAppToken;
760        return isDrawnLw() && mPolicyVisibility
761            && ((!mAttachedHidden &&
762                    (atoken == null || !atoken.hiddenRequested))
763                    || mWinAnimator.mAnimating);
764    }
765
766    /**
767     * Return true if this window (or a window it is attached to, but not
768     * considering its app token) is currently animating.
769     */
770    public boolean isAnimatingLw() {
771        return mWinAnimator.mAnimation != null;
772    }
773
774    public boolean isGoneForLayoutLw() {
775        final AppWindowToken atoken = mAppToken;
776        return mViewVisibility == View.GONE
777                || !mRelayoutCalled
778                || (atoken == null && mRootToken.hidden)
779                || (atoken != null && (atoken.hiddenRequested || atoken.hidden))
780                || mAttachedHidden
781                || mExiting || mDestroying;
782    }
783
784    /**
785     * Returns true if the window has a surface that it has drawn a
786     * complete UI in to.
787     */
788    public boolean isDrawnLw() {
789        return mHasSurface && !mDestroying &&
790                (mWinAnimator.mDrawState == WindowStateAnimator.READY_TO_SHOW
791                || mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN);
792    }
793
794    /**
795     * Return true if the window is opaque and fully drawn.  This indicates
796     * it may obscure windows behind it.
797     */
798    boolean isOpaqueDrawn() {
799        return (mAttrs.format == PixelFormat.OPAQUE
800                        || mAttrs.type == TYPE_WALLPAPER)
801                && isDrawnLw() && mWinAnimator.mAnimation == null
802                && (mAppToken == null || mAppToken.mAppAnimator.animation == null);
803    }
804
805    /**
806     * Return whether this window is wanting to have a translation
807     * animation applied to it for an in-progress move.  (Only makes
808     * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
809     */
810    boolean shouldAnimateMove() {
811        return mContentChanged && !mExiting && !mWinAnimator.mLastHidden && mService.okToDisplay()
812                && (mFrame.top != mLastFrame.top
813                        || mFrame.left != mLastFrame.left)
814                && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove());
815    }
816
817    boolean isFullscreen(int screenWidth, int screenHeight) {
818        return mFrame.left <= 0 && mFrame.top <= 0 &&
819                mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
820    }
821
822    void removeLocked() {
823        disposeInputChannel();
824
825        if (mAttachedWindow != null) {
826            if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(TAG, "Removing " + this + " from " + mAttachedWindow);
827            mAttachedWindow.mChildWindows.remove(this);
828        }
829        mWinAnimator.destroyDeferredSurfaceLocked();
830        mWinAnimator.destroySurfaceLocked();
831        mSession.windowRemovedLocked();
832        try {
833            mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
834        } catch (RuntimeException e) {
835            // Ignore if it has already been removed (usually because
836            // we are doing this as part of processing a death note.)
837        }
838    }
839
840    void setInputChannel(InputChannel inputChannel) {
841        if (mInputChannel != null) {
842            throw new IllegalStateException("Window already has an input channel.");
843        }
844
845        mInputChannel = inputChannel;
846        mInputWindowHandle.inputChannel = inputChannel;
847    }
848
849    void disposeInputChannel() {
850        if (mInputChannel != null) {
851            mService.mInputManager.unregisterInputChannel(mInputChannel);
852
853            mInputChannel.dispose();
854            mInputChannel = null;
855        }
856
857        mInputWindowHandle.inputChannel = null;
858    }
859
860    private class DeathRecipient implements IBinder.DeathRecipient {
861        public void binderDied() {
862            try {
863                synchronized(mService.mWindowMap) {
864                    WindowState win = mService.windowForClientLocked(mSession, mClient, false);
865                    Slog.i(TAG, "WIN DEATH: " + win);
866                    if (win != null) {
867                        mService.removeWindowLocked(mSession, win);
868                    }
869                }
870            } catch (IllegalArgumentException ex) {
871                // This will happen if the window has already been
872                // removed.
873            }
874        }
875    }
876
877    /** Returns true if this window desires key events.
878     * TODO(cmautner): Is this the same as {@link WindowManagerService#canBeImeTarget}
879     */
880    public final boolean canReceiveKeys() {
881        return     isVisibleOrAdding()
882                && (mViewVisibility == View.VISIBLE)
883                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
884    }
885
886    @Override
887    public boolean hasDrawnLw() {
888        return mWinAnimator.mDrawState == WindowStateAnimator.HAS_DRAWN;
889    }
890
891    @Override
892    public boolean showLw(boolean doAnimation) {
893        return showLw(doAnimation, true);
894    }
895
896    boolean showLw(boolean doAnimation, boolean requestAnim) {
897        if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
898            // Already showing.
899            return false;
900        }
901        if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility true: " + this);
902        if (doAnimation) {
903            if (DEBUG_VISIBILITY) Slog.v(TAG, "doAnimation: mPolicyVisibility="
904                    + mPolicyVisibility + " mAnimation=" + mWinAnimator.mAnimation);
905            if (!mService.okToDisplay()) {
906                doAnimation = false;
907            } else if (mPolicyVisibility && mWinAnimator.mAnimation == null) {
908                // Check for the case where we are currently visible and
909                // not animating; we do not want to do animation at such a
910                // point to become visible when we already are.
911                doAnimation = false;
912            }
913        }
914        mPolicyVisibility = true;
915        mPolicyVisibilityAfterAnim = true;
916        if (doAnimation) {
917            mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_ENTER, true);
918        }
919        if (requestAnim) {
920            mService.updateLayoutToAnimationLocked();
921        }
922        return true;
923    }
924
925    @Override
926    public boolean hideLw(boolean doAnimation) {
927        return hideLw(doAnimation, true);
928    }
929
930    boolean hideLw(boolean doAnimation, boolean requestAnim) {
931        if (doAnimation) {
932            if (!mService.okToDisplay()) {
933                doAnimation = false;
934            }
935        }
936        boolean current = doAnimation ? mPolicyVisibilityAfterAnim
937                : mPolicyVisibility;
938        if (!current) {
939            // Already hiding.
940            return false;
941        }
942        if (doAnimation) {
943            mWinAnimator.applyAnimationLocked(WindowManagerPolicy.TRANSIT_EXIT, false);
944            if (mWinAnimator.mAnimation == null) {
945                doAnimation = false;
946            }
947        }
948        if (doAnimation) {
949            mPolicyVisibilityAfterAnim = false;
950        } else {
951            if (DEBUG_VISIBILITY) Slog.v(TAG, "Policy visibility false: " + this);
952            mPolicyVisibilityAfterAnim = false;
953            mPolicyVisibility = false;
954            // Window is no longer visible -- make sure if we were waiting
955            // for it to be displayed before enabling the display, that
956            // we allow the display to be enabled now.
957            mService.enableScreenIfNeededLocked();
958            if (mService.mCurrentFocus == this) {
959                mService.mFocusMayChange = true;
960            }
961        }
962        if (requestAnim) {
963            mService.updateLayoutToAnimationLocked();
964        }
965        return true;
966    }
967
968    @Override
969    public boolean isAlive() {
970        return mClient.asBinder().isBinderAlive();
971    }
972
973    private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
974        outRegion.set(
975                frame.left + inset.left, frame.top + inset.top,
976                frame.right - inset.right, frame.bottom - inset.bottom);
977    }
978
979    public void getTouchableRegion(Region outRegion) {
980        final Rect frame = mFrame;
981        switch (mTouchableInsets) {
982            default:
983            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
984                outRegion.set(frame);
985                break;
986            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:
987                applyInsets(outRegion, frame, mGivenContentInsets);
988                break;
989            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:
990                applyInsets(outRegion, frame, mGivenVisibleInsets);
991                break;
992            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
993                final Region givenTouchableRegion = mGivenTouchableRegion;
994                outRegion.set(givenTouchableRegion);
995                outRegion.translate(frame.left, frame.top);
996                break;
997            }
998        }
999    }
1000
1001    WindowList getWindowList() {
1002        return mDisplayContent.getWindowList();
1003    }
1004
1005    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1006        pw.print(prefix); pw.print("mDisplayId="); pw.print(mDisplayContent.getDisplayId());
1007                pw.print(" mSession="); pw.print(mSession);
1008                pw.print(" mClient="); pw.println(mClient.asBinder());
1009        pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
1010        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
1011                pw.print(" h="); pw.print(mRequestedHeight);
1012                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
1013        if (mRequestedWidth != mLastRequestedWidth || mRequestedHeight != mLastRequestedHeight) {
1014            pw.print(prefix); pw.print("LastRequested w="); pw.print(mLastRequestedWidth);
1015                    pw.print(" h="); pw.println(mLastRequestedHeight);
1016        }
1017        if (mAttachedWindow != null || mLayoutAttached) {
1018            pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
1019                    pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
1020        }
1021        if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
1022            pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
1023                    pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
1024                    pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
1025                    pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
1026        }
1027        if (dumpAll) {
1028            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
1029                    pw.print(" mSubLayer="); pw.print(mSubLayer);
1030                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
1031                    pw.print((mTargetAppToken != null ?
1032                            mTargetAppToken.mAppAnimator.animLayerAdjustment
1033                          : (mAppToken != null ? mAppToken.mAppAnimator.animLayerAdjustment : 0)));
1034                    pw.print("="); pw.print(mWinAnimator.mAnimLayer);
1035                    pw.print(" mLastLayer="); pw.println(mWinAnimator.mLastLayer);
1036        }
1037        if (dumpAll) {
1038            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
1039            pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
1040            if (mAppToken != null) {
1041                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
1042            }
1043            if (mTargetAppToken != null) {
1044                pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
1045            }
1046            pw.print(prefix); pw.print("mViewVisibility=0x");
1047            pw.print(Integer.toHexString(mViewVisibility));
1048            pw.print(" mHaveFrame="); pw.print(mHaveFrame);
1049            pw.print(" mObscured="); pw.println(mObscured);
1050            pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
1051            pw.print(" mSystemUiVisibility=0x");
1052            pw.println(Integer.toHexString(mSystemUiVisibility));
1053        }
1054        if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
1055            pw.print(prefix); pw.print("mPolicyVisibility=");
1056                    pw.print(mPolicyVisibility);
1057                    pw.print(" mPolicyVisibilityAfterAnim=");
1058                    pw.print(mPolicyVisibilityAfterAnim);
1059                    pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
1060        }
1061        if (!mRelayoutCalled || mLayoutNeeded) {
1062            pw.print(prefix); pw.print("mRelayoutCalled="); pw.print(mRelayoutCalled);
1063                    pw.print(" mLayoutNeeded="); pw.println(mLayoutNeeded);
1064        }
1065        if (mXOffset != 0 || mYOffset != 0) {
1066            pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
1067                    pw.print(" y="); pw.println(mYOffset);
1068        }
1069        if (dumpAll) {
1070            pw.print(prefix); pw.print("mGivenContentInsets=");
1071                    mGivenContentInsets.printShortString(pw);
1072                    pw.print(" mGivenVisibleInsets=");
1073                    mGivenVisibleInsets.printShortString(pw);
1074                    pw.println();
1075            if (mTouchableInsets != 0 || mGivenInsetsPending) {
1076                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
1077                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
1078                Region region = new Region();
1079                getTouchableRegion(region);
1080                pw.print(prefix); pw.print("touchable region="); pw.println(region);
1081            }
1082            pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
1083        }
1084        pw.print(prefix); pw.print("mHasSurface="); pw.print(mHasSurface);
1085                pw.print(" mShownFrame="); mShownFrame.printShortString(pw); pw.println();
1086        if (dumpAll) {
1087            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
1088                    pw.print(" last="); mLastFrame.printShortString(pw);
1089                    pw.println();
1090            pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
1091                    pw.print(" last="); mLastSystemDecorRect.printShortString(pw);
1092                    pw.println();
1093        }
1094        if (mEnforceSizeCompat) {
1095            pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
1096                    pw.println();
1097        }
1098        if (dumpAll) {
1099            pw.print(prefix); pw.print("Frames: containing=");
1100                    mContainingFrame.printShortString(pw);
1101                    pw.print(" parent="); mParentFrame.printShortString(pw);
1102                    pw.print(" display="); mDisplayFrame.printShortString(pw);
1103                    pw.println();
1104            pw.print(prefix); pw.print("    content="); mContentFrame.printShortString(pw);
1105                    pw.print(" visible="); mVisibleFrame.printShortString(pw);
1106                    pw.println();
1107            pw.print(prefix); pw.print("Cur insets: content=");
1108                    mContentInsets.printShortString(pw);
1109                    pw.print(" visible="); mVisibleInsets.printShortString(pw);
1110                    pw.println();
1111            pw.print(prefix); pw.print("Lst insets: content=");
1112                    mLastContentInsets.printShortString(pw);
1113                    pw.print(" visible="); mLastVisibleInsets.printShortString(pw);
1114                    pw.println();
1115        }
1116        mWinAnimator.dump(pw, prefix, dumpAll);
1117        if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
1118            pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
1119                    pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
1120                    pw.print(" mDestroying="); pw.print(mDestroying);
1121                    pw.print(" mRemoved="); pw.println(mRemoved);
1122        }
1123        if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
1124            pw.print(prefix); pw.print("mOrientationChanging=");
1125                    pw.print(mOrientationChanging);
1126                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
1127                    pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
1128        }
1129        if (mHScale != 1 || mVScale != 1) {
1130            pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
1131                    pw.print(" mVScale="); pw.println(mVScale);
1132        }
1133        if (mWallpaperX != -1 || mWallpaperY != -1) {
1134            pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
1135                    pw.print(" mWallpaperY="); pw.println(mWallpaperY);
1136        }
1137        if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
1138            pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
1139                    pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
1140        }
1141    }
1142
1143    String makeInputChannelName() {
1144        return Integer.toHexString(System.identityHashCode(this))
1145            + " " + mAttrs.getTitle();
1146    }
1147
1148    @Override
1149    public String toString() {
1150        if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
1151                || mWasPaused != mToken.paused) {
1152            mLastTitle = mAttrs.getTitle();
1153            mWasPaused = mToken.paused;
1154            mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
1155                    + " " + mLastTitle + " paused=" + mWasPaused + "}";
1156        }
1157        return mStringNameCache;
1158    }
1159}
1160