WindowState.java revision 526f0a0e158cf46c244edc57624c15ebce26c71f
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_APPLICATION_STARTING;
23import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
24import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
25import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
26
27import com.android.server.wm.WindowManagerService.H;
28
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.Gravity;
39import android.view.IApplicationToken;
40import android.view.IWindow;
41import android.view.InputChannel;
42import android.view.Surface;
43import android.view.View;
44import android.view.ViewTreeObserver;
45import android.view.WindowManager;
46import android.view.WindowManagerPolicy;
47import android.view.WindowManager.LayoutParams;
48import android.view.animation.Animation;
49import android.view.animation.Transformation;
50
51import java.io.PrintWriter;
52import java.util.ArrayList;
53
54/**
55 * A window in the window manager.
56 */
57final class WindowState implements WindowManagerPolicy.WindowState {
58    static final boolean DEBUG_VISIBILITY = WindowManagerService.DEBUG_VISIBILITY;
59    static final boolean SHOW_TRANSACTIONS = WindowManagerService.SHOW_TRANSACTIONS;
60    static final boolean SHOW_LIGHT_TRANSACTIONS = WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
61    static final boolean SHOW_SURFACE_ALLOC = WindowManagerService.SHOW_SURFACE_ALLOC;
62
63    final WindowManagerService mService;
64    final Session mSession;
65    final IWindow mClient;
66    WindowToken mToken;
67    WindowToken mRootToken;
68    AppWindowToken mAppToken;
69    AppWindowToken mTargetAppToken;
70    final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
71    final DeathRecipient mDeathRecipient;
72    final WindowState mAttachedWindow;
73    final ArrayList<WindowState> mChildWindows = new ArrayList<WindowState>();
74    final int mBaseLayer;
75    final int mSubLayer;
76    final boolean mLayoutAttached;
77    final boolean mIsImWindow;
78    final boolean mIsWallpaper;
79    final boolean mIsFloatingLayer;
80    int mSeq;
81    boolean mEnforceSizeCompat;
82    int mViewVisibility;
83    int mSystemUiVisibility;
84    boolean mPolicyVisibility = true;
85    boolean mPolicyVisibilityAfterAnim = true;
86    boolean mAppFreezing;
87    Surface mSurface;
88    boolean mReportDestroySurface;
89    boolean mSurfacePendingDestroy;
90    boolean mAttachedHidden;    // is our parent window hidden?
91    boolean mLastHidden;        // was this window last hidden?
92    boolean mWallpaperVisible;  // for wallpaper, what was last vis report?
93
94    /**
95     * The window size that was requested by the application.  These are in
96     * the application's coordinate space (without compatibility scale applied).
97     */
98    int mRequestedWidth;
99    int mRequestedHeight;
100
101    int mLayer;
102    int mAnimLayer;
103    int mLastLayer;
104    boolean mHaveFrame;
105    boolean mObscured;
106    boolean mTurnOnScreen;
107
108    int mLayoutSeq = -1;
109
110    Configuration mConfiguration = null;
111
112    /**
113     * Actual frame shown on-screen (may be modified by animation).  These
114     * are in the screen's coordinate space (WITH the compatibility scale
115     * applied).
116     */
117    final RectF mShownFrame = new RectF();
118
119    /**
120     * Set when we have changed the size of the surface, to know that
121     * we must tell them application to resize (and thus redraw itself).
122     */
123    boolean mSurfaceResized;
124
125    /**
126     * Insets that determine the actually visible area.  These are in the application's
127     * coordinate space (without compatibility scale applied).
128     */
129    final Rect mVisibleInsets = new Rect();
130    final Rect mLastVisibleInsets = new Rect();
131    boolean mVisibleInsetsChanged;
132
133    /**
134     * Insets that are covered by system windows.  These are in the application's
135     * coordinate space (without compatibility scale applied).
136     */
137    final Rect mContentInsets = new Rect();
138    final Rect mLastContentInsets = new Rect();
139    boolean mContentInsetsChanged;
140
141    /**
142     * Set to true if we are waiting for this window to receive its
143     * given internal insets before laying out other windows based on it.
144     */
145    boolean mGivenInsetsPending;
146
147    /**
148     * These are the content insets that were given during layout for
149     * this window, to be applied to windows behind it.
150     */
151    final Rect mGivenContentInsets = new Rect();
152
153    /**
154     * These are the visible insets that were given during layout for
155     * this window, to be applied to windows behind it.
156     */
157    final Rect mGivenVisibleInsets = new Rect();
158
159    /**
160     * This is the given touchable area relative to the window frame, or null if none.
161     */
162    final Region mGivenTouchableRegion = new Region();
163
164    /**
165     * Flag indicating whether the touchable region should be adjusted by
166     * the visible insets; if false the area outside the visible insets is
167     * NOT touchable, so we must use those to adjust the frame during hit
168     * tests.
169     */
170    int mTouchableInsets = ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME;
171
172    // Current transformation being applied.
173    boolean mHaveMatrix;
174    float mGlobalScale=1;
175    float mInvGlobalScale=1;
176    float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
177    float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
178    float mHScale=1, mVScale=1;
179    float mLastHScale=1, mLastVScale=1;
180    final Matrix mTmpMatrix = new Matrix();
181
182    // "Real" frame that the application sees, in display coordinate space.
183    final Rect mFrame = new Rect();
184    final Rect mLastFrame = new Rect();
185    // Frame that is scaled to the application's coordinate space when in
186    // screen size compatibility mode.
187    final Rect mCompatFrame = new Rect();
188
189    final Rect mContainingFrame = new Rect();
190    final Rect mDisplayFrame = new Rect();
191    final Rect mContentFrame = new Rect();
192    final Rect mParentFrame = new Rect();
193    final Rect mVisibleFrame = new Rect();
194
195    boolean mContentChanged;
196
197    float mShownAlpha = 1;
198    float mAlpha = 1;
199    float mLastAlpha = 1;
200
201    // Set to true if, when the window gets displayed, it should perform
202    // an enter animation.
203    boolean mEnterAnimationPending;
204
205    // Currently running animation.
206    boolean mAnimating;
207    boolean mLocalAnimating;
208    Animation mAnimation;
209    boolean mAnimationIsEntrance;
210    boolean mHasTransformation;
211    boolean mHasLocalTransformation;
212    final Transformation mTransformation = new Transformation();
213
214    // If a window showing a wallpaper: the requested offset for the
215    // wallpaper; if a wallpaper window: the currently applied offset.
216    float mWallpaperX = -1;
217    float mWallpaperY = -1;
218
219    // If a window showing a wallpaper: what fraction of the offset
220    // range corresponds to a full virtual screen.
221    float mWallpaperXStep = -1;
222    float mWallpaperYStep = -1;
223
224    // Wallpaper windows: pixels offset based on above variables.
225    int mXOffset;
226    int mYOffset;
227
228    // This is set after IWindowSession.relayout() has been called at
229    // least once for the window.  It allows us to detect the situation
230    // where we don't yet have a surface, but should have one soon, so
231    // we can give the window focus before waiting for the relayout.
232    boolean mRelayoutCalled;
233
234    // This is set after the Surface has been created but before the
235    // window has been drawn.  During this time the surface is hidden.
236    boolean mDrawPending;
237
238    // This is set after the window has finished drawing for the first
239    // time but before its surface is shown.  The surface will be
240    // displayed when the next layout is run.
241    boolean mCommitDrawPending;
242
243    // This is set during the time after the window's drawing has been
244    // committed, and before its surface is actually shown.  It is used
245    // to delay showing the surface until all windows in a token are ready
246    // to be shown.
247    boolean mReadyToShow;
248
249    // Set when the window has been shown in the screen the first time.
250    boolean mHasDrawn;
251
252    // Currently running an exit animation?
253    boolean mExiting;
254
255    // Currently on the mDestroySurface list?
256    boolean mDestroying;
257
258    // Completely remove from window manager after exit animation?
259    boolean mRemoveOnExit;
260
261    // Set when the orientation is changing and this window has not yet
262    // been updated for the new orientation.
263    boolean mOrientationChanging;
264
265    // Is this window now (or just being) removed?
266    boolean mRemoved;
267
268    // Temp for keeping track of windows that have been removed when
269    // rebuilding window list.
270    boolean mRebuilding;
271
272    // For debugging, this is the last information given to the surface flinger.
273    boolean mSurfaceShown;
274    float mSurfaceX, mSurfaceY, mSurfaceW, mSurfaceH;
275    int mSurfaceLayer;
276    float mSurfaceAlpha;
277
278    // Input channel and input window handle used by the input dispatcher.
279    final InputWindowHandle mInputWindowHandle;
280    InputChannel mInputChannel;
281
282    // Used to improve performance of toString()
283    String mStringNameCache;
284    CharSequence mLastTitle;
285    boolean mWasPaused;
286
287    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
288           WindowState attachedWindow, int seq, WindowManager.LayoutParams a,
289           int viewVisibility) {
290        mService = service;
291        mSession = s;
292        mClient = c;
293        mToken = token;
294        mAttrs.copyFrom(a);
295        mViewVisibility = viewVisibility;
296        DeathRecipient deathRecipient = new DeathRecipient();
297        mAlpha = a.alpha;
298        mSeq = seq;
299        mEnforceSizeCompat = (mAttrs.flags & FLAG_COMPATIBLE_WINDOW) != 0;
300        if (WindowManagerService.localLOGV) Slog.v(
301            WindowManagerService.TAG, "Window " + this + " client=" + c.asBinder()
302            + " token=" + token + " (" + mAttrs.token + ")");
303        try {
304            c.asBinder().linkToDeath(deathRecipient, 0);
305        } catch (RemoteException e) {
306            mDeathRecipient = null;
307            mAttachedWindow = null;
308            mLayoutAttached = false;
309            mIsImWindow = false;
310            mIsWallpaper = false;
311            mIsFloatingLayer = false;
312            mBaseLayer = 0;
313            mSubLayer = 0;
314            mInputWindowHandle = null;
315            return;
316        }
317        mDeathRecipient = deathRecipient;
318
319        if ((mAttrs.type >= FIRST_SUB_WINDOW &&
320                mAttrs.type <= LAST_SUB_WINDOW)) {
321            // The multiplier here is to reserve space for multiple
322            // windows in the same type layer.
323            mBaseLayer = mService.mPolicy.windowTypeToLayerLw(
324                    attachedWindow.mAttrs.type) * WindowManagerService.TYPE_LAYER_MULTIPLIER
325                    + WindowManagerService.TYPE_LAYER_OFFSET;
326            mSubLayer = mService.mPolicy.subWindowTypeToLayerLw(a.type);
327            mAttachedWindow = attachedWindow;
328            if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Adding " + this + " to " + mAttachedWindow);
329            mAttachedWindow.mChildWindows.add(this);
330            mLayoutAttached = mAttrs.type !=
331                    WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
332            mIsImWindow = attachedWindow.mAttrs.type == TYPE_INPUT_METHOD
333                    || attachedWindow.mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
334            mIsWallpaper = attachedWindow.mAttrs.type == TYPE_WALLPAPER;
335            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
336        } else {
337            // The multiplier here is to reserve space for multiple
338            // windows in the same type layer.
339            mBaseLayer = mService.mPolicy.windowTypeToLayerLw(a.type)
340                    * WindowManagerService.TYPE_LAYER_MULTIPLIER
341                    + WindowManagerService.TYPE_LAYER_OFFSET;
342            mSubLayer = 0;
343            mAttachedWindow = null;
344            mLayoutAttached = false;
345            mIsImWindow = mAttrs.type == TYPE_INPUT_METHOD
346                    || mAttrs.type == TYPE_INPUT_METHOD_DIALOG;
347            mIsWallpaper = mAttrs.type == TYPE_WALLPAPER;
348            mIsFloatingLayer = mIsImWindow || mIsWallpaper;
349        }
350
351        WindowState appWin = this;
352        while (appWin.mAttachedWindow != null) {
353            appWin = mAttachedWindow;
354        }
355        WindowToken appToken = appWin.mToken;
356        while (appToken.appWindowToken == null) {
357            WindowToken parent = mService.mTokenMap.get(appToken.token);
358            if (parent == null || appToken == parent) {
359                break;
360            }
361            appToken = parent;
362        }
363        mRootToken = appToken;
364        mAppToken = appToken.appWindowToken;
365
366        mSurface = null;
367        mRequestedWidth = 0;
368        mRequestedHeight = 0;
369        mXOffset = 0;
370        mYOffset = 0;
371        mLayer = 0;
372        mAnimLayer = 0;
373        mLastLayer = 0;
374        mInputWindowHandle = new InputWindowHandle(
375                mAppToken != null ? mAppToken.mInputApplicationHandle : null, this);
376    }
377
378    void attach() {
379        if (WindowManagerService.localLOGV) Slog.v(
380            WindowManagerService.TAG, "Attaching " + this + " token=" + mToken
381            + ", list=" + mToken.windows);
382        mSession.windowAddedLocked();
383    }
384
385    public void computeFrameLw(Rect pf, Rect df, Rect cf, Rect vf) {
386        mHaveFrame = true;
387
388        final Rect container = mContainingFrame;
389        container.set(pf);
390
391        final Rect display = mDisplayFrame;
392        display.set(df);
393
394        final int pw = container.right - container.left;
395        final int ph = container.bottom - container.top;
396
397        int w,h;
398        if ((mAttrs.flags & WindowManager.LayoutParams.FLAG_SCALED) != 0) {
399            if (mAttrs.width < 0) {
400                w = pw;
401            } else if (mEnforceSizeCompat) {
402                w = (int)(mAttrs.width * mGlobalScale + .5f);
403            } else {
404                w = mAttrs.width;
405            }
406            if (mAttrs.height < 0) {
407                h = ph;
408            } else if (mEnforceSizeCompat) {
409                h = (int)(mAttrs.height * mGlobalScale + .5f);
410            } else {
411                h = mAttrs.height;
412            }
413        } else {
414            if (mAttrs.width == WindowManager.LayoutParams.MATCH_PARENT) {
415                w = pw;
416            } else if (mEnforceSizeCompat) {
417                w = (int)(mRequestedWidth * mGlobalScale + .5f);
418            } else {
419                w = mRequestedWidth;
420            }
421            if (mAttrs.height == WindowManager.LayoutParams.MATCH_PARENT) {
422                h = ph;
423            } else if (mEnforceSizeCompat) {
424                h = (int)(mRequestedHeight * mGlobalScale + .5f);
425            } else {
426                h = mRequestedHeight;
427            }
428        }
429
430        if (!mParentFrame.equals(pf)) {
431            //Slog.i(TAG, "Window " + this + " content frame from " + mParentFrame
432            //        + " to " + pf);
433            mParentFrame.set(pf);
434            mContentChanged = true;
435        }
436
437        final Rect content = mContentFrame;
438        content.set(cf);
439
440        final Rect visible = mVisibleFrame;
441        visible.set(vf);
442
443        final Rect frame = mFrame;
444        final int fw = frame.width();
445        final int fh = frame.height();
446
447        //System.out.println("In: w=" + w + " h=" + h + " container=" +
448        //                   container + " x=" + mAttrs.x + " y=" + mAttrs.y);
449
450        float x, y;
451        if (mEnforceSizeCompat) {
452            x = mAttrs.x * mGlobalScale;
453            y = mAttrs.y * mGlobalScale;
454        } else {
455            x = mAttrs.x;
456            y = mAttrs.y;
457        }
458
459        Gravity.apply(mAttrs.gravity, w, h, container,
460                (int) (x + mAttrs.horizontalMargin * pw),
461                (int) (y + mAttrs.verticalMargin * ph), frame);
462
463        //System.out.println("Out: " + mFrame);
464
465        // Now make sure the window fits in the overall display.
466        Gravity.applyDisplay(mAttrs.gravity, df, frame);
467
468        // Make sure the content and visible frames are inside of the
469        // final window frame.
470        if (content.left < frame.left) content.left = frame.left;
471        if (content.top < frame.top) content.top = frame.top;
472        if (content.right > frame.right) content.right = frame.right;
473        if (content.bottom > frame.bottom) content.bottom = frame.bottom;
474        if (visible.left < frame.left) visible.left = frame.left;
475        if (visible.top < frame.top) visible.top = frame.top;
476        if (visible.right > frame.right) visible.right = frame.right;
477        if (visible.bottom > frame.bottom) visible.bottom = frame.bottom;
478
479        final Rect contentInsets = mContentInsets;
480        contentInsets.left = content.left-frame.left;
481        contentInsets.top = content.top-frame.top;
482        contentInsets.right = frame.right-content.right;
483        contentInsets.bottom = frame.bottom-content.bottom;
484
485        final Rect visibleInsets = mVisibleInsets;
486        visibleInsets.left = visible.left-frame.left;
487        visibleInsets.top = visible.top-frame.top;
488        visibleInsets.right = frame.right-visible.right;
489        visibleInsets.bottom = frame.bottom-visible.bottom;
490
491        mCompatFrame.set(frame);
492        if (mEnforceSizeCompat) {
493            // If there is a size compatibility scale being applied to the
494            // window, we need to apply this to its insets so that they are
495            // reported to the app in its coordinate space.
496            contentInsets.scale(mInvGlobalScale);
497            visibleInsets.scale(mInvGlobalScale);
498
499            // Also the scaled frame that we report to the app needs to be
500            // adjusted to be in its coordinate space.
501            mCompatFrame.scale(mInvGlobalScale);
502        }
503
504        if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
505            mService.updateWallpaperOffsetLocked(this,
506                    mService.mAppDisplayWidth, mService.mAppDisplayHeight, false);
507        }
508
509        if (WindowManagerService.localLOGV) {
510            //if ("com.google.android.youtube".equals(mAttrs.packageName)
511            //        && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
512                Slog.v(WindowManagerService.TAG, "Resolving (mRequestedWidth="
513                        + mRequestedWidth + ", mRequestedheight="
514                        + mRequestedHeight + ") to" + " (pw=" + pw + ", ph=" + ph
515                        + "): frame=" + mFrame.toShortString()
516                        + " ci=" + contentInsets.toShortString()
517                        + " vi=" + visibleInsets.toShortString());
518            //}
519        }
520    }
521
522    public Rect getFrameLw() {
523        return mFrame;
524    }
525
526    public RectF getShownFrameLw() {
527        return mShownFrame;
528    }
529
530    public Rect getDisplayFrameLw() {
531        return mDisplayFrame;
532    }
533
534    public Rect getContentFrameLw() {
535        return mContentFrame;
536    }
537
538    public Rect getVisibleFrameLw() {
539        return mVisibleFrame;
540    }
541
542    public boolean getGivenInsetsPendingLw() {
543        return mGivenInsetsPending;
544    }
545
546    public Rect getGivenContentInsetsLw() {
547        return mGivenContentInsets;
548    }
549
550    public Rect getGivenVisibleInsetsLw() {
551        return mGivenVisibleInsets;
552    }
553
554    public WindowManager.LayoutParams getAttrs() {
555        return mAttrs;
556    }
557
558    public int getSystemUiVisibility() {
559        return mSystemUiVisibility;
560    }
561
562    public int getSurfaceLayer() {
563        return mLayer;
564    }
565
566    public IApplicationToken getAppToken() {
567        return mAppToken != null ? mAppToken.appToken : null;
568    }
569
570    public long getInputDispatchingTimeoutNanos() {
571        return mAppToken != null
572                ? mAppToken.inputDispatchingTimeoutNanos
573                : WindowManagerService.DEFAULT_INPUT_DISPATCHING_TIMEOUT_NANOS;
574    }
575
576    public boolean hasAppShownWindows() {
577        return mAppToken != null ? mAppToken.firstWindowDrawn : false;
578    }
579
580    public void setAnimation(Animation anim) {
581        if (WindowManagerService.localLOGV) Slog.v(
582            WindowManagerService.TAG, "Setting animation in " + this + ": " + anim);
583        mAnimating = false;
584        mLocalAnimating = false;
585        mAnimation = anim;
586        mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
587        mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
588    }
589
590    public void clearAnimation() {
591        if (mAnimation != null) {
592            mAnimating = true;
593            mLocalAnimating = false;
594            mAnimation.cancel();
595            mAnimation = null;
596        }
597    }
598
599    Surface createSurfaceLocked() {
600        if (mSurface == null) {
601            mReportDestroySurface = false;
602            mSurfacePendingDestroy = false;
603            mDrawPending = true;
604            mCommitDrawPending = false;
605            mReadyToShow = false;
606            if (mAppToken != null) {
607                mAppToken.allDrawn = false;
608            }
609
610            int flags = 0;
611
612            if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
613                flags |= Surface.SECURE;
614            }
615            if (DEBUG_VISIBILITY) Slog.v(
616                WindowManagerService.TAG, "Creating surface in session "
617                + mSession.mSurfaceSession + " window " + this
618                + " w=" + mCompatFrame.width()
619                + " h=" + mCompatFrame.height() + " format="
620                + mAttrs.format + " flags=" + flags);
621
622            int w = mCompatFrame.width();
623            int h = mCompatFrame.height();
624            if ((mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
625                // for a scaled surface, we always want the requested
626                // size.
627                w = mRequestedWidth;
628                h = mRequestedHeight;
629            }
630
631            // Something is wrong and SurfaceFlinger will not like this,
632            // try to revert to sane values
633            if (w <= 0) w = 1;
634            if (h <= 0) h = 1;
635
636            mSurfaceShown = false;
637            mSurfaceLayer = 0;
638            mSurfaceAlpha = 1;
639            mSurfaceX = 0;
640            mSurfaceY = 0;
641            mSurfaceW = w;
642            mSurfaceH = h;
643            try {
644                final boolean isHwAccelerated = (mAttrs.flags &
645                        WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
646                final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : mAttrs.format;
647                if (!PixelFormat.formatHasAlpha(mAttrs.format)) {
648                    flags |= Surface.OPAQUE;
649                }
650                mSurface = new Surface(
651                        mSession.mSurfaceSession, mSession.mPid,
652                        mAttrs.getTitle().toString(),
653                        0, w, h, format, flags);
654                if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(WindowManagerService.TAG,
655                        "  CREATE SURFACE "
656                        + mSurface + " IN SESSION "
657                        + mSession.mSurfaceSession
658                        + ": pid=" + mSession.mPid + " format="
659                        + mAttrs.format + " flags=0x"
660                        + Integer.toHexString(flags)
661                        + " / " + this);
662            } catch (Surface.OutOfResourcesException e) {
663                Slog.w(WindowManagerService.TAG, "OutOfResourcesException creating surface");
664                mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
665                return null;
666            } catch (Exception e) {
667                Slog.e(WindowManagerService.TAG, "Exception creating surface", e);
668                return null;
669            }
670
671            if (WindowManagerService.localLOGV) Slog.v(
672                WindowManagerService.TAG, "Got surface: " + mSurface
673                + ", set left=" + mFrame.left + " top=" + mFrame.top
674                + ", animLayer=" + mAnimLayer);
675            if (SHOW_LIGHT_TRANSACTIONS) {
676                Slog.i(WindowManagerService.TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
677                WindowManagerService.logSurface(this, "CREATE pos=(" + mFrame.left
678                        + "," + mFrame.top + ") (" +
679                        mCompatFrame.width() + "x" + mCompatFrame.height() + "), layer=" +
680                        mAnimLayer + " HIDE", null);
681            }
682            Surface.openTransaction();
683            try {
684                try {
685                    mSurfaceX = mFrame.left + mXOffset;
686                    mSurfaceY = mFrame.top + mYOffset;
687                    mSurface.setPosition(mSurfaceX, mSurfaceY);
688                    mSurfaceLayer = mAnimLayer;
689                    mSurface.setLayer(mAnimLayer);
690                    mSurfaceShown = false;
691                    mSurface.hide();
692                    if ((mAttrs.flags&WindowManager.LayoutParams.FLAG_DITHER) != 0) {
693                        if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "DITHER", null);
694                        mSurface.setFlags(Surface.SURFACE_DITHER,
695                                Surface.SURFACE_DITHER);
696                    }
697                } catch (RuntimeException e) {
698                    Slog.w(WindowManagerService.TAG, "Error creating surface in " + w, e);
699                    mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
700                }
701                mLastHidden = true;
702            } finally {
703                Surface.closeTransaction();
704                if (SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
705                        "<<< CLOSE TRANSACTION createSurfaceLocked");
706            }
707            if (WindowManagerService.localLOGV) Slog.v(
708                    WindowManagerService.TAG, "Created surface " + this);
709        }
710        return mSurface;
711    }
712
713    void destroySurfaceLocked() {
714        if (mAppToken != null && this == mAppToken.startingWindow) {
715            mAppToken.startingDisplayed = false;
716        }
717
718        if (mSurface != null) {
719            mDrawPending = false;
720            mCommitDrawPending = false;
721            mReadyToShow = false;
722
723            int i = mChildWindows.size();
724            while (i > 0) {
725                i--;
726                WindowState c = mChildWindows.get(i);
727                c.mAttachedHidden = true;
728            }
729
730            if (mReportDestroySurface) {
731                mReportDestroySurface = false;
732                mSurfacePendingDestroy = true;
733                try {
734                    mClient.dispatchGetNewSurface();
735                    // We'll really destroy on the next time around.
736                    return;
737                } catch (RemoteException e) {
738                }
739            }
740
741            try {
742                if (DEBUG_VISIBILITY) {
743                    RuntimeException e = null;
744                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
745                        e = new RuntimeException();
746                        e.fillInStackTrace();
747                    }
748                    Slog.w(WindowManagerService.TAG, "Window " + this + " destroying surface "
749                            + mSurface + ", session " + mSession, e);
750                }
751                if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
752                    RuntimeException e = null;
753                    if (!WindowManagerService.HIDE_STACK_CRAWLS) {
754                        e = new RuntimeException();
755                        e.fillInStackTrace();
756                    }
757                    WindowManagerService.logSurface(this, "DESTROY", e);
758                }
759                mSurface.destroy();
760            } catch (RuntimeException e) {
761                Slog.w(WindowManagerService.TAG, "Exception thrown when destroying Window " + this
762                    + " surface " + mSurface + " session " + mSession
763                    + ": " + e.toString());
764            }
765
766            mSurfaceShown = false;
767            mSurface = null;
768        }
769    }
770
771    boolean finishDrawingLocked() {
772        if (mDrawPending) {
773            if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) Slog.v(
774                WindowManagerService.TAG, "finishDrawingLocked: " + mSurface);
775            mCommitDrawPending = true;
776            mDrawPending = false;
777            return true;
778        }
779        return false;
780    }
781
782    // This must be called while inside a transaction.
783    boolean commitFinishDrawingLocked(long currentTime) {
784        //Slog.i(TAG, "commitFinishDrawingLocked: " + mSurface);
785        if (!mCommitDrawPending) {
786            return false;
787        }
788        mCommitDrawPending = false;
789        mReadyToShow = true;
790        final boolean starting = mAttrs.type == TYPE_APPLICATION_STARTING;
791        final AppWindowToken atoken = mAppToken;
792        if (atoken == null || atoken.allDrawn || starting) {
793            performShowLocked();
794        }
795        return true;
796    }
797
798    // This must be called while inside a transaction.
799    boolean performShowLocked() {
800        if (DEBUG_VISIBILITY) {
801            RuntimeException e = null;
802            if (!WindowManagerService.HIDE_STACK_CRAWLS) {
803                e = new RuntimeException();
804                e.fillInStackTrace();
805            }
806            Slog.v(WindowManagerService.TAG, "performShow on " + this
807                    + ": readyToShow=" + mReadyToShow + " readyForDisplay=" + isReadyForDisplay()
808                    + " starting=" + (mAttrs.type == TYPE_APPLICATION_STARTING), e);
809        }
810        if (mReadyToShow && isReadyForDisplay()) {
811            if (SHOW_TRANSACTIONS || WindowManagerService.DEBUG_ORIENTATION) WindowManagerService.logSurface(this,
812                    "SHOW (performShowLocked)", null);
813            if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Showing " + this
814                    + " during animation: policyVis=" + mPolicyVisibility
815                    + " attHidden=" + mAttachedHidden
816                    + " tok.hiddenRequested="
817                    + (mAppToken != null ? mAppToken.hiddenRequested : false)
818                    + " tok.hidden="
819                    + (mAppToken != null ? mAppToken.hidden : false)
820                    + " animating=" + mAnimating
821                    + " tok animating="
822                    + (mAppToken != null ? mAppToken.animating : false));
823            if (!mService.showSurfaceRobustlyLocked(this)) {
824                return false;
825            }
826            mLastAlpha = -1;
827            mHasDrawn = true;
828            mLastHidden = false;
829            mReadyToShow = false;
830            mService.enableScreenIfNeededLocked();
831
832            mService.applyEnterAnimationLocked(this);
833
834            int i = mChildWindows.size();
835            while (i > 0) {
836                i--;
837                WindowState c = mChildWindows.get(i);
838                if (c.mAttachedHidden) {
839                    c.mAttachedHidden = false;
840                    if (c.mSurface != null) {
841                        c.performShowLocked();
842                        // It hadn't been shown, which means layout not
843                        // performed on it, so now we want to make sure to
844                        // do a layout.  If called from within the transaction
845                        // loop, this will cause it to restart with a new
846                        // layout.
847                        mService.mLayoutNeeded = true;
848                    }
849                }
850            }
851
852            if (mAttrs.type != TYPE_APPLICATION_STARTING
853                    && mAppToken != null) {
854                mAppToken.firstWindowDrawn = true;
855
856                if (mAppToken.startingData != null) {
857                    if (WindowManagerService.DEBUG_STARTING_WINDOW || WindowManagerService.DEBUG_ANIM) Slog.v(WindowManagerService.TAG,
858                            "Finish starting " + mToken
859                            + ": first real window is shown, no animation");
860                    // If this initial window is animating, stop it -- we
861                    // will do an animation to reveal it from behind the
862                    // starting window, so there is no need for it to also
863                    // be doing its own stuff.
864                    if (mAnimation != null) {
865                        mAnimation.cancel();
866                        mAnimation = null;
867                        // Make sure we clean up the animation.
868                        mAnimating = true;
869                    }
870                    mService.mFinishedStarting.add(mAppToken);
871                    mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
872                }
873                mAppToken.updateReportedVisibilityLocked();
874            }
875        }
876        return true;
877    }
878
879    // This must be called while inside a transaction.  Returns true if
880    // there is more animation to run.
881    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
882        if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOnFully()) {
883            // We will run animations as long as the display isn't frozen.
884
885            if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
886                mHasTransformation = true;
887                mHasLocalTransformation = true;
888                if (!mLocalAnimating) {
889                    if (WindowManagerService.DEBUG_ANIM) Slog.v(
890                        WindowManagerService.TAG, "Starting animation in " + this +
891                        " @ " + currentTime + ": ww=" + mFrame.width() +
892                        " wh=" + mFrame.height() +
893                        " dw=" + dw + " dh=" + dh + " scale=" + mService.mWindowAnimationScale);
894                    mAnimation.initialize(mFrame.width(), mFrame.height(), dw, dh);
895                    mAnimation.setStartTime(currentTime);
896                    mLocalAnimating = true;
897                    mAnimating = true;
898                }
899                mTransformation.clear();
900                final boolean more = mAnimation.getTransformation(
901                    currentTime, mTransformation);
902                if (WindowManagerService.DEBUG_ANIM) Slog.v(
903                    WindowManagerService.TAG, "Stepped animation in " + this +
904                    ": more=" + more + ", xform=" + mTransformation);
905                if (more) {
906                    // we're not done!
907                    return true;
908                }
909                if (WindowManagerService.DEBUG_ANIM) Slog.v(
910                    WindowManagerService.TAG, "Finished animation in " + this +
911                    " @ " + currentTime);
912
913                if (mAnimation != null) {
914                    mAnimation.cancel();
915                    mAnimation = null;
916                }
917                //WindowManagerService.this.dump();
918            }
919            mHasLocalTransformation = false;
920            if ((!mLocalAnimating || mAnimationIsEntrance) && mAppToken != null
921                    && mAppToken.animation != null) {
922                // When our app token is animating, we kind-of pretend like
923                // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
924                // part of this check means that we will only do this if
925                // our window is not currently exiting, or it is not
926                // locally animating itself.  The idea being that one that
927                // is exiting and doing a local animation should be removed
928                // once that animation is done.
929                mAnimating = true;
930                mHasTransformation = true;
931                mTransformation.clear();
932                return false;
933            } else if (mHasTransformation) {
934                // Little trick to get through the path below to act like
935                // we have finished an animation.
936                mAnimating = true;
937            } else if (isAnimating()) {
938                mAnimating = true;
939            }
940        } else if (mAnimation != null) {
941            // If the display is frozen, and there is a pending animation,
942            // clear it and make sure we run the cleanup code.
943            mAnimating = true;
944            mLocalAnimating = true;
945            mAnimation.cancel();
946            mAnimation = null;
947        }
948
949        if (!mAnimating && !mLocalAnimating) {
950            return false;
951        }
952
953        if (WindowManagerService.DEBUG_ANIM) Slog.v(
954            WindowManagerService.TAG, "Animation done in " + this + ": exiting=" + mExiting
955            + ", reportedVisible="
956            + (mAppToken != null ? mAppToken.reportedVisible : false));
957
958        mAnimating = false;
959        mLocalAnimating = false;
960        if (mAnimation != null) {
961            mAnimation.cancel();
962            mAnimation = null;
963        }
964        mAnimLayer = mLayer;
965        if (mIsImWindow) {
966            mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
967        } else if (mIsWallpaper) {
968            mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
969        }
970        if (WindowManagerService.DEBUG_LAYERS) Slog.v(WindowManagerService.TAG, "Stepping win " + this
971                + " anim layer: " + mAnimLayer);
972        mHasTransformation = false;
973        mHasLocalTransformation = false;
974        if (mPolicyVisibility != mPolicyVisibilityAfterAnim) {
975            if (DEBUG_VISIBILITY) {
976                Slog.v(WindowManagerService.TAG, "Policy visibility changing after anim in " + this + ": "
977                        + mPolicyVisibilityAfterAnim);
978            }
979            mPolicyVisibility = mPolicyVisibilityAfterAnim;
980            mService.mLayoutNeeded = true;
981            if (!mPolicyVisibility) {
982                if (mService.mCurrentFocus == this) {
983                    mService.mFocusMayChange = true;
984                }
985                // Window is no longer visible -- make sure if we were waiting
986                // for it to be displayed before enabling the display, that
987                // we allow the display to be enabled now.
988                mService.enableScreenIfNeededLocked();
989            }
990        }
991        mTransformation.clear();
992        if (mHasDrawn
993                && mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
994                && mAppToken != null
995                && mAppToken.firstWindowDrawn
996                && mAppToken.startingData != null) {
997            if (WindowManagerService.DEBUG_STARTING_WINDOW) Slog.v(WindowManagerService.TAG, "Finish starting "
998                    + mToken + ": first real window done animating");
999            mService.mFinishedStarting.add(mAppToken);
1000            mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
1001        }
1002
1003        finishExit();
1004
1005        if (mAppToken != null) {
1006            mAppToken.updateReportedVisibilityLocked();
1007        }
1008
1009        return false;
1010    }
1011
1012    void finishExit() {
1013        if (WindowManagerService.DEBUG_ANIM) Slog.v(
1014                WindowManagerService.TAG, "finishExit in " + this
1015                + ": exiting=" + mExiting
1016                + " remove=" + mRemoveOnExit
1017                + " windowAnimating=" + isWindowAnimating());
1018
1019        final int N = mChildWindows.size();
1020        for (int i=0; i<N; i++) {
1021            mChildWindows.get(i).finishExit();
1022        }
1023
1024        if (!mExiting) {
1025            return;
1026        }
1027
1028        if (isWindowAnimating()) {
1029            return;
1030        }
1031
1032        if (WindowManagerService.localLOGV) Slog.v(
1033                WindowManagerService.TAG, "Exit animation finished in " + this
1034                + ": remove=" + mRemoveOnExit);
1035        if (mSurface != null) {
1036            mService.mDestroySurface.add(this);
1037            mDestroying = true;
1038            if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(this, "HIDE (finishExit)", null);
1039            mSurfaceShown = false;
1040            try {
1041                mSurface.hide();
1042            } catch (RuntimeException e) {
1043                Slog.w(WindowManagerService.TAG, "Error hiding surface in " + this, e);
1044            }
1045            mLastHidden = true;
1046        }
1047        mExiting = false;
1048        if (mRemoveOnExit) {
1049            mService.mPendingRemove.add(this);
1050            mRemoveOnExit = false;
1051        }
1052    }
1053
1054    boolean isIdentityMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
1055        if (dsdx < .99999f || dsdx > 1.00001f) return false;
1056        if (dtdy < .99999f || dtdy > 1.00001f) return false;
1057        if (dtdx < -.000001f || dtdx > .000001f) return false;
1058        if (dsdy < -.000001f || dsdy > .000001f) return false;
1059        return true;
1060    }
1061
1062    void prelayout() {
1063        if (mEnforceSizeCompat) {
1064            mGlobalScale = mService.mCompatibleScreenScale;
1065            mInvGlobalScale = 1/mGlobalScale;
1066        } else {
1067            mGlobalScale = mInvGlobalScale = 1;
1068        }
1069    }
1070
1071    void computeShownFrameLocked() {
1072        final boolean selfTransformation = mHasLocalTransformation;
1073        Transformation attachedTransformation =
1074                (mAttachedWindow != null && mAttachedWindow.mHasLocalTransformation)
1075                ? mAttachedWindow.mTransformation : null;
1076        Transformation appTransformation =
1077                (mAppToken != null && mAppToken.hasTransformation)
1078                ? mAppToken.transformation : null;
1079
1080        // Wallpapers are animated based on the "real" window they
1081        // are currently targeting.
1082        if (mAttrs.type == TYPE_WALLPAPER && mService.mLowerWallpaperTarget == null
1083                && mService.mWallpaperTarget != null) {
1084            if (mService.mWallpaperTarget.mHasLocalTransformation &&
1085                    mService.mWallpaperTarget.mAnimation != null &&
1086                    !mService.mWallpaperTarget.mAnimation.getDetachWallpaper()) {
1087                attachedTransformation = mService.mWallpaperTarget.mTransformation;
1088                if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
1089                    Slog.v(WindowManagerService.TAG, "WP target attached xform: " + attachedTransformation);
1090                }
1091            }
1092            if (mService.mWallpaperTarget.mAppToken != null &&
1093                    mService.mWallpaperTarget.mAppToken.hasTransformation &&
1094                    mService.mWallpaperTarget.mAppToken.animation != null &&
1095                    !mService.mWallpaperTarget.mAppToken.animation.getDetachWallpaper()) {
1096                appTransformation = mService.mWallpaperTarget.mAppToken.transformation;
1097                if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
1098                    Slog.v(WindowManagerService.TAG, "WP target app xform: " + appTransformation);
1099                }
1100            }
1101        }
1102
1103        final boolean screenAnimation = mService.mScreenRotationAnimation != null
1104                && mService.mScreenRotationAnimation.isAnimating();
1105        if (selfTransformation || attachedTransformation != null
1106                || appTransformation != null || screenAnimation) {
1107            // cache often used attributes locally
1108            final Rect frame = mFrame;
1109            final float tmpFloats[] = mService.mTmpFloats;
1110            final Matrix tmpMatrix = mTmpMatrix;
1111
1112            // Compute the desired transformation.
1113            if (screenAnimation) {
1114                // If we are doing a screen animation, the global rotation
1115                // applied to windows can result in windows that are carefully
1116                // aligned with each other to slightly separate, allowing you
1117                // to see what is behind them.  An unsightly mess.  This...
1118                // thing...  magically makes it call good: scale each window
1119                // slightly (two pixels larger in each dimension, from the
1120                // window's center).
1121                final float w = frame.width();
1122                final float h = frame.height();
1123                if (w>=1 && h>=1) {
1124                    tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
1125                } else {
1126                    tmpMatrix.reset();
1127                }
1128            } else {
1129                tmpMatrix.reset();
1130            }
1131            tmpMatrix.postScale(mGlobalScale, mGlobalScale);
1132            if (selfTransformation) {
1133                tmpMatrix.postConcat(mTransformation.getMatrix());
1134            }
1135            tmpMatrix.postTranslate(frame.left + mXOffset, frame.top + mYOffset);
1136            if (attachedTransformation != null) {
1137                tmpMatrix.postConcat(attachedTransformation.getMatrix());
1138            }
1139            if (appTransformation != null) {
1140                tmpMatrix.postConcat(appTransformation.getMatrix());
1141            }
1142            if (screenAnimation) {
1143                tmpMatrix.postConcat(
1144                        mService.mScreenRotationAnimation.getEnterTransformation().getMatrix());
1145            }
1146
1147            // "convert" it into SurfaceFlinger's format
1148            // (a 2x2 matrix + an offset)
1149            // Here we must not transform the position of the surface
1150            // since it is already included in the transformation.
1151            //Slog.i(TAG, "Transform: " + matrix);
1152
1153            mHaveMatrix = true;
1154            tmpMatrix.getValues(tmpFloats);
1155            mDsDx = tmpFloats[Matrix.MSCALE_X];
1156            mDtDx = tmpFloats[Matrix.MSKEW_Y];
1157            mDsDy = tmpFloats[Matrix.MSKEW_X];
1158            mDtDy = tmpFloats[Matrix.MSCALE_Y];
1159            float x = tmpFloats[Matrix.MTRANS_X];
1160            float y = tmpFloats[Matrix.MTRANS_Y];
1161            int w = frame.width();
1162            int h = frame.height();
1163            mShownFrame.set(x, y, x+w, y+h);
1164
1165            // Now set the alpha...  but because our current hardware
1166            // can't do alpha transformation on a non-opaque surface,
1167            // turn it off if we are running an animation that is also
1168            // transforming since it is more important to have that
1169            // animation be smooth.
1170            mShownAlpha = mAlpha;
1171            if (!mService.mLimitedAlphaCompositing
1172                    || (!PixelFormat.formatHasAlpha(mAttrs.format)
1173                    || (isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
1174                            && x == frame.left && y == frame.top))) {
1175                //Slog.i(TAG, "Applying alpha transform");
1176                if (selfTransformation) {
1177                    mShownAlpha *= mTransformation.getAlpha();
1178                }
1179                if (attachedTransformation != null) {
1180                    mShownAlpha *= attachedTransformation.getAlpha();
1181                }
1182                if (appTransformation != null) {
1183                    mShownAlpha *= appTransformation.getAlpha();
1184                }
1185                if (screenAnimation) {
1186                    mShownAlpha *=
1187                        mService.mScreenRotationAnimation.getEnterTransformation().getAlpha();
1188                }
1189            } else {
1190                //Slog.i(TAG, "Not applying alpha transform");
1191            }
1192
1193            if (WindowManagerService.localLOGV) Slog.v(
1194                WindowManagerService.TAG, "Continuing animation in " + this +
1195                ": " + mShownFrame +
1196                ", alpha=" + mTransformation.getAlpha());
1197            return;
1198        }
1199
1200        mShownFrame.set(mFrame);
1201        if (mXOffset != 0 || mYOffset != 0) {
1202            mShownFrame.offset(mXOffset, mYOffset);
1203        }
1204        mShownAlpha = mAlpha;
1205        mHaveMatrix = false;
1206        mDsDx = mGlobalScale;
1207        mDtDx = 0;
1208        mDsDy = 0;
1209        mDtDy = mGlobalScale;
1210    }
1211
1212    /**
1213     * Is this window visible?  It is not visible if there is no
1214     * surface, or we are in the process of running an exit animation
1215     * that will remove the surface, or its app token has been hidden.
1216     */
1217    public boolean isVisibleLw() {
1218        final AppWindowToken atoken = mAppToken;
1219        return mSurface != null && mPolicyVisibility && !mAttachedHidden
1220                && (atoken == null || !atoken.hiddenRequested)
1221                && !mExiting && !mDestroying;
1222    }
1223
1224    /**
1225     * Like {@link #isVisibleLw}, but also counts a window that is currently
1226     * "hidden" behind the keyguard as visible.  This allows us to apply
1227     * things like window flags that impact the keyguard.
1228     * XXX I am starting to think we need to have ANOTHER visibility flag
1229     * for this "hidden behind keyguard" state rather than overloading
1230     * mPolicyVisibility.  Ungh.
1231     */
1232    public boolean isVisibleOrBehindKeyguardLw() {
1233        if (mRootToken.waitingToShow &&
1234                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
1235            return false;
1236        }
1237        final AppWindowToken atoken = mAppToken;
1238        final boolean animating = atoken != null
1239                ? (atoken.animation != null) : false;
1240        return mSurface != null && !mDestroying && !mExiting
1241                && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
1242                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
1243                                && !mRootToken.hidden)
1244                        || mAnimation != null || animating);
1245    }
1246
1247    /**
1248     * Is this window visible, ignoring its app token?  It is not visible
1249     * if there is no surface, or we are in the process of running an exit animation
1250     * that will remove the surface.
1251     */
1252    public boolean isWinVisibleLw() {
1253        final AppWindowToken atoken = mAppToken;
1254        return mSurface != null && mPolicyVisibility && !mAttachedHidden
1255                && (atoken == null || !atoken.hiddenRequested || atoken.animating)
1256                && !mExiting && !mDestroying;
1257    }
1258
1259    /**
1260     * The same as isVisible(), but follows the current hidden state of
1261     * the associated app token, not the pending requested hidden state.
1262     */
1263    boolean isVisibleNow() {
1264        return mSurface != null && mPolicyVisibility && !mAttachedHidden
1265                && !mRootToken.hidden && !mExiting && !mDestroying;
1266    }
1267
1268    /**
1269     * Can this window possibly be a drag/drop target?  The test here is
1270     * a combination of the above "visible now" with the check that the
1271     * Input Manager uses when discarding windows from input consideration.
1272     */
1273    boolean isPotentialDragTarget() {
1274        return isVisibleNow() && !mRemoved
1275                && mInputChannel != null && mInputWindowHandle != null;
1276    }
1277
1278    /**
1279     * Same as isVisible(), but we also count it as visible between the
1280     * call to IWindowSession.add() and the first relayout().
1281     */
1282    boolean isVisibleOrAdding() {
1283        final AppWindowToken atoken = mAppToken;
1284        return ((mSurface != null && !mReportDestroySurface)
1285                        || (!mRelayoutCalled && mViewVisibility == View.VISIBLE))
1286                && mPolicyVisibility && !mAttachedHidden
1287                && (atoken == null || !atoken.hiddenRequested)
1288                && !mExiting && !mDestroying;
1289    }
1290
1291    /**
1292     * Is this window currently on-screen?  It is on-screen either if it
1293     * is visible or it is currently running an animation before no longer
1294     * being visible.
1295     */
1296    boolean isOnScreen() {
1297        final AppWindowToken atoken = mAppToken;
1298        if (atoken != null) {
1299            return mSurface != null && mPolicyVisibility && !mDestroying
1300                    && ((!mAttachedHidden && !atoken.hiddenRequested)
1301                            || mAnimation != null || atoken.animation != null);
1302        } else {
1303            return mSurface != null && mPolicyVisibility && !mDestroying
1304                    && (!mAttachedHidden || mAnimation != null);
1305        }
1306    }
1307
1308    /**
1309     * Like isOnScreen(), but we don't return true if the window is part
1310     * of a transition that has not yet been started.
1311     */
1312    boolean isReadyForDisplay() {
1313        if (mRootToken.waitingToShow &&
1314                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
1315            return false;
1316        }
1317        final AppWindowToken atoken = mAppToken;
1318        final boolean animating = atoken != null
1319                ? (atoken.animation != null) : false;
1320        return mSurface != null && mPolicyVisibility && !mDestroying
1321                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
1322                                && !mRootToken.hidden)
1323                        || mAnimation != null || animating);
1324    }
1325
1326    /** Is the window or its container currently animating? */
1327    boolean isAnimating() {
1328        final WindowState attached = mAttachedWindow;
1329        final AppWindowToken atoken = mAppToken;
1330        return mAnimation != null
1331                || (attached != null && attached.mAnimation != null)
1332                || (atoken != null &&
1333                        (atoken.animation != null
1334                                || atoken.inPendingTransaction));
1335    }
1336
1337    /** Is this window currently animating? */
1338    boolean isWindowAnimating() {
1339        return mAnimation != null;
1340    }
1341
1342    /**
1343     * Like isOnScreen, but returns false if the surface hasn't yet
1344     * been drawn.
1345     */
1346    public boolean isDisplayedLw() {
1347        final AppWindowToken atoken = mAppToken;
1348        return mSurface != null && mPolicyVisibility && !mDestroying
1349            && !mDrawPending && !mCommitDrawPending
1350            && ((!mAttachedHidden &&
1351                    (atoken == null || !atoken.hiddenRequested))
1352                    || mAnimating);
1353    }
1354
1355    /**
1356     * Returns true if the window has a surface that it has drawn a
1357     * complete UI in to.
1358     */
1359    public boolean isDrawnLw() {
1360        final AppWindowToken atoken = mAppToken;
1361        return mSurface != null && !mDestroying
1362            && !mDrawPending && !mCommitDrawPending;
1363    }
1364
1365    /**
1366     * Return true if the window is opaque and fully drawn.  This indicates
1367     * it may obscure windows behind it.
1368     */
1369    boolean isOpaqueDrawn() {
1370        return (mAttrs.format == PixelFormat.OPAQUE
1371                        || mAttrs.type == TYPE_WALLPAPER)
1372                && mSurface != null && mAnimation == null
1373                && (mAppToken == null || mAppToken.animation == null)
1374                && !mDrawPending && !mCommitDrawPending;
1375    }
1376
1377    /**
1378     * Return whether this window is wanting to have a translation
1379     * animation applied to it for an in-progress move.  (Only makes
1380     * sense to call from performLayoutAndPlaceSurfacesLockedInner().)
1381     */
1382    boolean shouldAnimateMove() {
1383        return mContentChanged && !mExiting && !mLastHidden && !mService.mDisplayFrozen
1384                && (mFrame.top != mLastFrame.top
1385                        || mFrame.left != mLastFrame.left)
1386                && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
1387                && mService.mPolicy.isScreenOnFully();
1388    }
1389
1390    boolean isFullscreen(int screenWidth, int screenHeight) {
1391        return mFrame.left <= 0 && mFrame.top <= 0 &&
1392                mFrame.right >= screenWidth && mFrame.bottom >= screenHeight;
1393    }
1394
1395    void removeLocked() {
1396        disposeInputChannel();
1397
1398        if (mAttachedWindow != null) {
1399            if (WindowManagerService.DEBUG_ADD_REMOVE) Slog.v(WindowManagerService.TAG, "Removing " + this + " from " + mAttachedWindow);
1400            mAttachedWindow.mChildWindows.remove(this);
1401        }
1402        destroySurfaceLocked();
1403        mSession.windowRemovedLocked();
1404        try {
1405            mClient.asBinder().unlinkToDeath(mDeathRecipient, 0);
1406        } catch (RuntimeException e) {
1407            // Ignore if it has already been removed (usually because
1408            // we are doing this as part of processing a death note.)
1409        }
1410    }
1411
1412    void setInputChannel(InputChannel inputChannel) {
1413        if (mInputChannel != null) {
1414            throw new IllegalStateException("Window already has an input channel.");
1415        }
1416
1417        mInputChannel = inputChannel;
1418        mInputWindowHandle.inputChannel = inputChannel;
1419    }
1420
1421    void disposeInputChannel() {
1422        if (mInputChannel != null) {
1423            mService.mInputManager.unregisterInputChannel(mInputChannel);
1424
1425            mInputChannel.dispose();
1426            mInputChannel = null;
1427        }
1428
1429        mInputWindowHandle.inputChannel = null;
1430    }
1431
1432    private class DeathRecipient implements IBinder.DeathRecipient {
1433        public void binderDied() {
1434            try {
1435                synchronized(mService.mWindowMap) {
1436                    WindowState win = mService.windowForClientLocked(mSession, mClient, false);
1437                    Slog.i(WindowManagerService.TAG, "WIN DEATH: " + win);
1438                    if (win != null) {
1439                        mService.removeWindowLocked(mSession, win);
1440                    }
1441                }
1442            } catch (IllegalArgumentException ex) {
1443                // This will happen if the window has already been
1444                // removed.
1445            }
1446        }
1447    }
1448
1449    /** Returns true if this window desires key events. */
1450    public final boolean canReceiveKeys() {
1451        return     isVisibleOrAdding()
1452                && (mViewVisibility == View.VISIBLE)
1453                && ((mAttrs.flags & WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) == 0);
1454    }
1455
1456    public boolean hasDrawnLw() {
1457        return mHasDrawn;
1458    }
1459
1460    public boolean showLw(boolean doAnimation) {
1461        return showLw(doAnimation, true);
1462    }
1463
1464    boolean showLw(boolean doAnimation, boolean requestAnim) {
1465        if (mPolicyVisibility && mPolicyVisibilityAfterAnim) {
1466            return false;
1467        }
1468        if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility true: " + this);
1469        if (doAnimation) {
1470            if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
1471                    + mPolicyVisibility + " mAnimation=" + mAnimation);
1472            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
1473                doAnimation = false;
1474            } else if (mPolicyVisibility && mAnimation == null) {
1475                // Check for the case where we are currently visible and
1476                // not animating; we do not want to do animation at such a
1477                // point to become visible when we already are.
1478                doAnimation = false;
1479            }
1480        }
1481        mPolicyVisibility = true;
1482        mPolicyVisibilityAfterAnim = true;
1483        if (doAnimation) {
1484            mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_ENTER, true);
1485        }
1486        if (requestAnim) {
1487            mService.requestAnimationLocked(0);
1488        }
1489        return true;
1490    }
1491
1492    public boolean hideLw(boolean doAnimation) {
1493        return hideLw(doAnimation, true);
1494    }
1495
1496    boolean hideLw(boolean doAnimation, boolean requestAnim) {
1497        if (doAnimation) {
1498            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
1499                doAnimation = false;
1500            }
1501        }
1502        boolean current = doAnimation ? mPolicyVisibilityAfterAnim
1503                : mPolicyVisibility;
1504        if (!current) {
1505            return false;
1506        }
1507        if (doAnimation) {
1508            mService.applyAnimationLocked(this, WindowManagerPolicy.TRANSIT_EXIT, false);
1509            if (mAnimation == null) {
1510                doAnimation = false;
1511            }
1512        }
1513        if (doAnimation) {
1514            mPolicyVisibilityAfterAnim = false;
1515        } else {
1516            if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "Policy visibility false: " + this);
1517            mPolicyVisibilityAfterAnim = false;
1518            mPolicyVisibility = false;
1519            // Window is no longer visible -- make sure if we were waiting
1520            // for it to be displayed before enabling the display, that
1521            // we allow the display to be enabled now.
1522            mService.enableScreenIfNeededLocked();
1523            if (mService.mCurrentFocus == this) {
1524                mService.mFocusMayChange = true;
1525            }
1526        }
1527        if (requestAnim) {
1528            mService.requestAnimationLocked(0);
1529        }
1530        return true;
1531    }
1532
1533    private static void applyInsets(Region outRegion, Rect frame, Rect inset) {
1534        outRegion.set(
1535                frame.left + inset.left, frame.top + inset.top,
1536                frame.right - inset.right, frame.bottom - inset.bottom);
1537    }
1538
1539    public void getTouchableRegion(Region outRegion) {
1540        final Rect frame = mFrame;
1541        switch (mTouchableInsets) {
1542            default:
1543            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
1544                outRegion.set(frame);
1545                break;
1546            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:
1547                applyInsets(outRegion, frame, mGivenContentInsets);
1548                break;
1549            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:
1550                applyInsets(outRegion, frame, mGivenVisibleInsets);
1551                break;
1552            case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION: {
1553                final Region givenTouchableRegion = mGivenTouchableRegion;
1554                outRegion.set(givenTouchableRegion);
1555                outRegion.translate(frame.left, frame.top);
1556                break;
1557            }
1558        }
1559    }
1560
1561    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1562        pw.print(prefix); pw.print("mSession="); pw.print(mSession);
1563                pw.print(" mClient="); pw.println(mClient.asBinder());
1564        pw.print(prefix); pw.print("mAttrs="); pw.println(mAttrs);
1565        pw.print(prefix); pw.print("Requested w="); pw.print(mRequestedWidth);
1566                pw.print(" h="); pw.print(mRequestedHeight);
1567                pw.print(" mLayoutSeq="); pw.println(mLayoutSeq);
1568        if (mAttachedWindow != null || mLayoutAttached) {
1569            pw.print(prefix); pw.print("mAttachedWindow="); pw.print(mAttachedWindow);
1570                    pw.print(" mLayoutAttached="); pw.println(mLayoutAttached);
1571        }
1572        if (mIsImWindow || mIsWallpaper || mIsFloatingLayer) {
1573            pw.print(prefix); pw.print("mIsImWindow="); pw.print(mIsImWindow);
1574                    pw.print(" mIsWallpaper="); pw.print(mIsWallpaper);
1575                    pw.print(" mIsFloatingLayer="); pw.print(mIsFloatingLayer);
1576                    pw.print(" mWallpaperVisible="); pw.println(mWallpaperVisible);
1577        }
1578        if (dumpAll) {
1579            pw.print(prefix); pw.print("mBaseLayer="); pw.print(mBaseLayer);
1580                    pw.print(" mSubLayer="); pw.print(mSubLayer);
1581                    pw.print(" mAnimLayer="); pw.print(mLayer); pw.print("+");
1582                    pw.print((mTargetAppToken != null ? mTargetAppToken.animLayerAdjustment
1583                          : (mAppToken != null ? mAppToken.animLayerAdjustment : 0)));
1584                    pw.print("="); pw.print(mAnimLayer);
1585                    pw.print(" mLastLayer="); pw.println(mLastLayer);
1586        }
1587        if (mSurface != null) {
1588            if (dumpAll) {
1589                pw.print(prefix); pw.print("mSurface="); pw.println(mSurface);
1590            }
1591            pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
1592                    pw.print(" layer="); pw.print(mSurfaceLayer);
1593                    pw.print(" alpha="); pw.print(mSurfaceAlpha);
1594                    pw.print(" rect=("); pw.print(mSurfaceX);
1595                    pw.print(","); pw.print(mSurfaceY);
1596                    pw.print(") "); pw.print(mSurfaceW);
1597                    pw.print(" x "); pw.println(mSurfaceH);
1598        }
1599        if (dumpAll) {
1600            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
1601            pw.print(prefix); pw.print("mRootToken="); pw.println(mRootToken);
1602            if (mAppToken != null) {
1603                pw.print(prefix); pw.print("mAppToken="); pw.println(mAppToken);
1604            }
1605            if (mTargetAppToken != null) {
1606                pw.print(prefix); pw.print("mTargetAppToken="); pw.println(mTargetAppToken);
1607            }
1608            pw.print(prefix); pw.print("mViewVisibility=0x");
1609            pw.print(Integer.toHexString(mViewVisibility));
1610            pw.print(" mLastHidden="); pw.print(mLastHidden);
1611            pw.print(" mHaveFrame="); pw.print(mHaveFrame);
1612            pw.print(" mObscured="); pw.println(mObscured);
1613            pw.print(prefix); pw.print("mSeq="); pw.print(mSeq);
1614            pw.print(" mSystemUiVisibility=0x");
1615            pw.println(Integer.toHexString(mSystemUiVisibility));
1616        }
1617        if (!mPolicyVisibility || !mPolicyVisibilityAfterAnim || mAttachedHidden) {
1618            pw.print(prefix); pw.print("mPolicyVisibility=");
1619                    pw.print(mPolicyVisibility);
1620                    pw.print(" mPolicyVisibilityAfterAnim=");
1621                    pw.print(mPolicyVisibilityAfterAnim);
1622                    pw.print(" mAttachedHidden="); pw.println(mAttachedHidden);
1623        }
1624        if (!mRelayoutCalled) {
1625            pw.print(prefix); pw.print("mRelayoutCalled="); pw.println(mRelayoutCalled);
1626        }
1627        if (mXOffset != 0 || mYOffset != 0) {
1628            pw.print(prefix); pw.print("Offsets x="); pw.print(mXOffset);
1629                    pw.print(" y="); pw.println(mYOffset);
1630        }
1631        if (dumpAll) {
1632            pw.print(prefix); pw.print("mGivenContentInsets=");
1633                    mGivenContentInsets.printShortString(pw);
1634                    pw.print(" mGivenVisibleInsets=");
1635                    mGivenVisibleInsets.printShortString(pw);
1636                    pw.println();
1637            if (mTouchableInsets != 0 || mGivenInsetsPending) {
1638                pw.print(prefix); pw.print("mTouchableInsets="); pw.print(mTouchableInsets);
1639                        pw.print(" mGivenInsetsPending="); pw.println(mGivenInsetsPending);
1640            }
1641            pw.print(prefix); pw.print("mConfiguration="); pw.println(mConfiguration);
1642        }
1643        pw.print(prefix); pw.print("mShownFrame=");
1644                mShownFrame.printShortString(pw); pw.println();
1645        if (dumpAll) {
1646            pw.print(prefix); pw.print("mFrame="); mFrame.printShortString(pw);
1647                    pw.print(" last="); mLastFrame.printShortString(pw);
1648                    pw.println();
1649        }
1650        if (mEnforceSizeCompat) {
1651            pw.print(prefix); pw.print("mCompatFrame="); mCompatFrame.printShortString(pw);
1652                    pw.println();
1653        }
1654        if (dumpAll) {
1655            pw.print(prefix); pw.print("mContainingFrame=");
1656                    mContainingFrame.printShortString(pw);
1657                    pw.print(" mParentFrame=");
1658                    mParentFrame.printShortString(pw);
1659                    pw.print(" mDisplayFrame=");
1660                    mDisplayFrame.printShortString(pw);
1661                    pw.println();
1662            pw.print(prefix); pw.print("mContentFrame="); mContentFrame.printShortString(pw);
1663                    pw.print(" mVisibleFrame="); mVisibleFrame.printShortString(pw);
1664                    pw.println();
1665            pw.print(prefix); pw.print("mContentInsets="); mContentInsets.printShortString(pw);
1666                    pw.print(" last="); mLastContentInsets.printShortString(pw);
1667                    pw.print(" mVisibleInsets="); mVisibleInsets.printShortString(pw);
1668                    pw.print(" last="); mLastVisibleInsets.printShortString(pw);
1669                    pw.println();
1670        }
1671        if (mAnimating || mLocalAnimating || mAnimationIsEntrance
1672                || mAnimation != null) {
1673            pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
1674                    pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
1675                    pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
1676                    pw.print(" mAnimation="); pw.println(mAnimation);
1677        }
1678        if (mHasTransformation || mHasLocalTransformation) {
1679            pw.print(prefix); pw.print("XForm: has=");
1680                    pw.print(mHasTransformation);
1681                    pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
1682                    pw.print(" "); mTransformation.printShortString(pw);
1683                    pw.println();
1684        }
1685        if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
1686            pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
1687                    pw.print(" mAlpha="); pw.print(mAlpha);
1688                    pw.print(" mLastAlpha="); pw.println(mLastAlpha);
1689        }
1690        if (mHaveMatrix || mGlobalScale != 1) {
1691            pw.print(prefix); pw.print("mGlobalScale="); pw.print(mGlobalScale);
1692                    pw.print(" mDsDx="); pw.print(mDsDx);
1693                    pw.print(" mDtDx="); pw.print(mDtDx);
1694                    pw.print(" mDsDy="); pw.print(mDsDy);
1695                    pw.print(" mDtDy="); pw.println(mDtDy);
1696        }
1697        if (dumpAll) {
1698            pw.print(prefix); pw.print("mDrawPending="); pw.print(mDrawPending);
1699                    pw.print(" mCommitDrawPending="); pw.print(mCommitDrawPending);
1700                    pw.print(" mReadyToShow="); pw.print(mReadyToShow);
1701                    pw.print(" mHasDrawn="); pw.println(mHasDrawn);
1702        }
1703        if (mExiting || mRemoveOnExit || mDestroying || mRemoved) {
1704            pw.print(prefix); pw.print("mExiting="); pw.print(mExiting);
1705                    pw.print(" mRemoveOnExit="); pw.print(mRemoveOnExit);
1706                    pw.print(" mDestroying="); pw.print(mDestroying);
1707                    pw.print(" mRemoved="); pw.println(mRemoved);
1708        }
1709        if (mOrientationChanging || mAppFreezing || mTurnOnScreen) {
1710            pw.print(prefix); pw.print("mOrientationChanging=");
1711                    pw.print(mOrientationChanging);
1712                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
1713                    pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
1714        }
1715        if (mHScale != 1 || mVScale != 1) {
1716            pw.print(prefix); pw.print("mHScale="); pw.print(mHScale);
1717                    pw.print(" mVScale="); pw.println(mVScale);
1718        }
1719        if (mWallpaperX != -1 || mWallpaperY != -1) {
1720            pw.print(prefix); pw.print("mWallpaperX="); pw.print(mWallpaperX);
1721                    pw.print(" mWallpaperY="); pw.println(mWallpaperY);
1722        }
1723        if (mWallpaperXStep != -1 || mWallpaperYStep != -1) {
1724            pw.print(prefix); pw.print("mWallpaperXStep="); pw.print(mWallpaperXStep);
1725                    pw.print(" mWallpaperYStep="); pw.println(mWallpaperYStep);
1726        }
1727    }
1728
1729    String makeInputChannelName() {
1730        return Integer.toHexString(System.identityHashCode(this))
1731            + " " + mAttrs.getTitle();
1732    }
1733
1734    @Override
1735    public String toString() {
1736        if (mStringNameCache == null || mLastTitle != mAttrs.getTitle()
1737                || mWasPaused != mToken.paused) {
1738            mLastTitle = mAttrs.getTitle();
1739            mWasPaused = mToken.paused;
1740            mStringNameCache = "Window{" + Integer.toHexString(System.identityHashCode(this))
1741                    + " " + mLastTitle + " paused=" + mWasPaused + "}";
1742        }
1743        return mStringNameCache;
1744    }
1745}