Home | History | Annotate | Download | only in wm
      1 /*
      2  * Copyright (C) 2014 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 
     17 package com.android.server.wm;
     18 
     19 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     20 import static com.android.server.wm.WindowManagerService.DEBUG_ANIM;
     21 import static com.android.server.wm.WindowManagerService.DEBUG_LAYERS;
     22 import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
     23 import static com.android.server.wm.WindowManagerService.DEBUG_STARTING_WINDOW;
     24 import static com.android.server.wm.WindowManagerService.DEBUG_SURFACE_TRACE;
     25 import static com.android.server.wm.WindowManagerService.SHOW_TRANSACTIONS;
     26 import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
     27 import static com.android.server.wm.WindowManagerService.SHOW_LIGHT_TRANSACTIONS;
     28 import static com.android.server.wm.WindowManagerService.SHOW_SURFACE_ALLOC;
     29 import static com.android.server.wm.WindowManagerService.localLOGV;
     30 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
     31 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_TURN_ON_SCREEN;
     32 
     33 import android.content.Context;
     34 import android.graphics.Matrix;
     35 import android.graphics.PixelFormat;
     36 import android.graphics.Point;
     37 import android.graphics.PointF;
     38 import android.graphics.Rect;
     39 import android.graphics.RectF;
     40 import android.graphics.Region;
     41 import android.os.Debug;
     42 import android.os.RemoteException;
     43 import android.util.Slog;
     44 import android.view.Display;
     45 import android.view.DisplayInfo;
     46 import android.view.MagnificationSpec;
     47 import android.view.Surface.OutOfResourcesException;
     48 import android.view.SurfaceControl;
     49 import android.view.SurfaceSession;
     50 import android.view.View;
     51 import android.view.WindowManager;
     52 import android.view.WindowManagerPolicy;
     53 import android.view.WindowManager.LayoutParams;
     54 import android.view.animation.Animation;
     55 import android.view.animation.AnimationSet;
     56 import android.view.animation.AnimationUtils;
     57 import android.view.animation.Transformation;
     58 
     59 import com.android.server.wm.WindowManagerService.H;
     60 
     61 import java.io.PrintWriter;
     62 import java.util.ArrayList;
     63 
     64 /**
     65  * Keep track of animations and surface operations for a single WindowState.
     66  **/
     67 class WindowStateAnimator {
     68     static final String TAG = "WindowStateAnimator";
     69 
     70     // Unchanging local convenience fields.
     71     final WindowManagerService mService;
     72     final WindowState mWin;
     73     final WindowStateAnimator mAttachedWinAnimator;
     74     final WindowAnimator mAnimator;
     75     AppWindowAnimator mAppAnimator;
     76     final Session mSession;
     77     final WindowManagerPolicy mPolicy;
     78     final Context mContext;
     79     final boolean mIsWallpaper;
     80 
     81     // Currently running animation.
     82     boolean mAnimating;
     83     boolean mLocalAnimating;
     84     Animation mAnimation;
     85     boolean mAnimationIsEntrance;
     86     boolean mHasTransformation;
     87     boolean mHasLocalTransformation;
     88     final Transformation mTransformation = new Transformation();
     89     boolean mWasAnimating;      // Were we animating going into the most recent animation step?
     90     int mAnimLayer;
     91     int mLastLayer;
     92     long mAnimationStartTime;
     93     long mLastAnimationTime;
     94 
     95     SurfaceControl mSurfaceControl;
     96     SurfaceControl mPendingDestroySurface;
     97 
     98     /**
     99      * Set when we have changed the size of the surface, to know that
    100      * we must tell them application to resize (and thus redraw itself).
    101      */
    102     boolean mSurfaceResized;
    103 
    104     /**
    105      * Set if the client has asked that the destroy of its surface be delayed
    106      * until it explicitly says it is okay.
    107      */
    108     boolean mSurfaceDestroyDeferred;
    109 
    110     float mShownAlpha = 0;
    111     float mAlpha = 0;
    112     float mLastAlpha = 0;
    113 
    114     boolean mHasClipRect;
    115     Rect mClipRect = new Rect();
    116     Rect mTmpClipRect = new Rect();
    117     Rect mLastClipRect = new Rect();
    118 
    119     // Used to save animation distances between the time they are calculated and when they are
    120     // used.
    121     int mAnimDw;
    122     int mAnimDh;
    123 
    124     /** Is the next animation to be started a window move animation? */
    125     boolean mAnimateMove = false;
    126 
    127     /** Are we currently running a window move animation? */
    128     boolean mAnimatingMove = false;
    129 
    130     float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
    131     float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
    132 
    133     boolean mHaveMatrix;
    134 
    135     // For debugging, this is the last information given to the surface flinger.
    136     boolean mSurfaceShown;
    137     float mSurfaceX, mSurfaceY;
    138     float mSurfaceW, mSurfaceH;
    139     int mSurfaceLayer;
    140     float mSurfaceAlpha;
    141 
    142     // Set to true if, when the window gets displayed, it should perform
    143     // an enter animation.
    144     boolean mEnterAnimationPending;
    145 
    146     /** Used to indicate that this window is undergoing an enter animation. Used for system
    147      * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
    148      * window is first added or shown, cleared when the callback has been made. */
    149     boolean mEnteringAnimation;
    150 
    151     boolean mKeyguardGoingAwayAnimation;
    152 
    153     /** The pixel format of the underlying SurfaceControl */
    154     int mSurfaceFormat;
    155 
    156     /** This is set when there is no Surface */
    157     static final int NO_SURFACE = 0;
    158     /** This is set after the Surface has been created but before the window has been drawn. During
    159      * this time the surface is hidden. */
    160     static final int DRAW_PENDING = 1;
    161     /** This is set after the window has finished drawing for the first time but before its surface
    162      * is shown.  The surface will be displayed when the next layout is run. */
    163     static final int COMMIT_DRAW_PENDING = 2;
    164     /** This is set during the time after the window's drawing has been committed, and before its
    165      * surface is actually shown.  It is used to delay showing the surface until all windows in a
    166      * token are ready to be shown. */
    167     static final int READY_TO_SHOW = 3;
    168     /** Set when the window has been shown in the screen the first time. */
    169     static final int HAS_DRAWN = 4;
    170 
    171     private static final int SYSTEM_UI_FLAGS_LAYOUT_STABLE_FULLSCREEN =
    172             View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
    173 
    174     String drawStateToString() {
    175         switch (mDrawState) {
    176             case NO_SURFACE: return "NO_SURFACE";
    177             case DRAW_PENDING: return "DRAW_PENDING";
    178             case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
    179             case READY_TO_SHOW: return "READY_TO_SHOW";
    180             case HAS_DRAWN: return "HAS_DRAWN";
    181             default: return Integer.toString(mDrawState);
    182         }
    183     }
    184     int mDrawState;
    185 
    186     /** Was this window last hidden? */
    187     boolean mLastHidden;
    188 
    189     int mAttrType;
    190 
    191     WindowStateAnimator(final WindowState win) {
    192         final WindowManagerService service = win.mService;
    193 
    194         mService = service;
    195         mAnimator = service.mAnimator;
    196         mPolicy = service.mPolicy;
    197         mContext = service.mContext;
    198         final DisplayContent displayContent = win.getDisplayContent();
    199         if (displayContent != null) {
    200             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    201             mAnimDw = displayInfo.appWidth;
    202             mAnimDh = displayInfo.appHeight;
    203         } else {
    204             Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed");
    205             // This is checked on return and dealt with.
    206         }
    207 
    208         mWin = win;
    209         mAttachedWinAnimator = win.mAttachedWindow == null
    210                 ? null : win.mAttachedWindow.mWinAnimator;
    211         mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
    212         mSession = win.mSession;
    213         mAttrType = win.mAttrs.type;
    214         mIsWallpaper = win.mIsWallpaper;
    215     }
    216 
    217     public void setAnimation(Animation anim, long startTime) {
    218         if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
    219         mAnimating = false;
    220         mLocalAnimating = false;
    221         mAnimation = anim;
    222         mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
    223         mAnimation.scaleCurrentDuration(mService.getWindowAnimationScaleLocked());
    224         // Start out animation gone if window is gone, or visible if window is visible.
    225         mTransformation.clear();
    226         mTransformation.setAlpha(mLastHidden ? 0 : 1);
    227         mHasLocalTransformation = true;
    228         mAnimationStartTime = startTime;
    229     }
    230 
    231     public void setAnimation(Animation anim) {
    232         setAnimation(anim, -1);
    233     }
    234 
    235     public void clearAnimation() {
    236         if (mAnimation != null) {
    237             mAnimating = true;
    238             mLocalAnimating = false;
    239             mAnimation.cancel();
    240             mAnimation = null;
    241             mKeyguardGoingAwayAnimation = false;
    242         }
    243     }
    244 
    245     /** Is the window or its container currently animating? */
    246     boolean isAnimating() {
    247         return mAnimation != null
    248                 || (mAttachedWinAnimator != null && mAttachedWinAnimator.mAnimation != null)
    249                 || (mAppAnimator != null && mAppAnimator.isAnimating());
    250     }
    251 
    252     /** Is the window animating the DummyAnimation? */
    253     boolean isDummyAnimation() {
    254         return mAppAnimator != null
    255                 && mAppAnimator.animation == AppWindowAnimator.sDummyAnimation;
    256     }
    257 
    258     /** Is this window currently set to animate or currently animating? */
    259     boolean isWindowAnimating() {
    260         return mAnimation != null;
    261     }
    262 
    263     void cancelExitAnimationForNextAnimationLocked() {
    264         if (mAnimation != null) {
    265             mAnimation.cancel();
    266             mAnimation = null;
    267             mLocalAnimating = false;
    268             destroySurfaceLocked();
    269         }
    270     }
    271 
    272     private boolean stepAnimation(long currentTime) {
    273         if ((mAnimation == null) || !mLocalAnimating) {
    274             return false;
    275         }
    276         mTransformation.clear();
    277         final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
    278         if (false && DEBUG_ANIM) Slog.v(
    279             TAG, "Stepped animation in " + this +
    280             ": more=" + more + ", xform=" + mTransformation);
    281         return more;
    282     }
    283 
    284     // This must be called while inside a transaction.  Returns true if
    285     // there is more animation to run.
    286     boolean stepAnimationLocked(long currentTime) {
    287         final DisplayContent displayContent = mWin.getDisplayContent();
    288         if (displayContent != null && mService.okToDisplay()) {
    289             // We will run animations as long as the display isn't frozen.
    290 
    291             if (mWin.isDrawnLw() && mAnimation != null) {
    292                 mHasTransformation = true;
    293                 mHasLocalTransformation = true;
    294                 if (!mLocalAnimating) {
    295                     if (DEBUG_ANIM) Slog.v(
    296                         TAG, "Starting animation in " + this +
    297                         " @ " + currentTime + ": ww=" + mWin.mFrame.width() +
    298                         " wh=" + mWin.mFrame.height() +
    299                         " dw=" + mAnimDw + " dh=" + mAnimDh +
    300                         " scale=" + mService.getWindowAnimationScaleLocked());
    301                     final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    302                     if (mAnimateMove) {
    303                         mAnimateMove = false;
    304                         mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
    305                                 mAnimDw, mAnimDh);
    306                     } else {
    307                         mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
    308                                 displayInfo.appWidth, displayInfo.appHeight);
    309                     }
    310                     mAnimDw = displayInfo.appWidth;
    311                     mAnimDh = displayInfo.appHeight;
    312                     mAnimation.setStartTime(mAnimationStartTime != -1
    313                             ? mAnimationStartTime
    314                             : currentTime);
    315                     mLocalAnimating = true;
    316                     mAnimating = true;
    317                 }
    318                 if ((mAnimation != null) && mLocalAnimating) {
    319                     mLastAnimationTime = currentTime;
    320                     if (stepAnimation(currentTime)) {
    321                         return true;
    322                     }
    323                 }
    324                 if (DEBUG_ANIM) Slog.v(
    325                     TAG, "Finished animation in " + this +
    326                     " @ " + currentTime);
    327                 //WindowManagerService.this.dump();
    328             }
    329             mHasLocalTransformation = false;
    330             if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null
    331                     && mAppAnimator.animation != null) {
    332                 // When our app token is animating, we kind-of pretend like
    333                 // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
    334                 // part of this check means that we will only do this if
    335                 // our window is not currently exiting, or it is not
    336                 // locally animating itself.  The idea being that one that
    337                 // is exiting and doing a local animation should be removed
    338                 // once that animation is done.
    339                 mAnimating = true;
    340                 mHasTransformation = true;
    341                 mTransformation.clear();
    342                 return false;
    343             } else if (mHasTransformation) {
    344                 // Little trick to get through the path below to act like
    345                 // we have finished an animation.
    346                 mAnimating = true;
    347             } else if (isAnimating()) {
    348                 mAnimating = true;
    349             }
    350         } else if (mAnimation != null) {
    351             // If the display is frozen, and there is a pending animation,
    352             // clear it and make sure we run the cleanup code.
    353             mAnimating = true;
    354         }
    355 
    356         if (!mAnimating && !mLocalAnimating) {
    357             return false;
    358         }
    359 
    360         // Done animating, clean up.
    361         if (DEBUG_ANIM) Slog.v(
    362             TAG, "Animation done in " + this + ": exiting=" + mWin.mExiting
    363             + ", reportedVisible="
    364             + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
    365 
    366         mAnimating = false;
    367         mKeyguardGoingAwayAnimation = false;
    368         mAnimatingMove = false;
    369         mLocalAnimating = false;
    370         if (mAnimation != null) {
    371             mAnimation.cancel();
    372             mAnimation = null;
    373         }
    374         if (mAnimator.mWindowDetachedWallpaper == mWin) {
    375             mAnimator.mWindowDetachedWallpaper = null;
    376         }
    377         mAnimLayer = mWin.mLayer;
    378         if (mWin.mIsImWindow) {
    379             mAnimLayer += mService.mInputMethodAnimLayerAdjustment;
    380         } else if (mIsWallpaper) {
    381             mAnimLayer += mService.mWallpaperAnimLayerAdjustment;
    382         }
    383         if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this
    384                 + " anim layer: " + mAnimLayer);
    385         mHasTransformation = false;
    386         mHasLocalTransformation = false;
    387         if (mWin.mPolicyVisibility != mWin.mPolicyVisibilityAfterAnim) {
    388             if (DEBUG_VISIBILITY) {
    389                 Slog.v(TAG, "Policy visibility changing after anim in " + this + ": "
    390                         + mWin.mPolicyVisibilityAfterAnim);
    391             }
    392             mWin.mPolicyVisibility = mWin.mPolicyVisibilityAfterAnim;
    393             if (displayContent != null) {
    394                 displayContent.layoutNeeded = true;
    395             }
    396             if (!mWin.mPolicyVisibility) {
    397                 if (mService.mCurrentFocus == mWin) {
    398                     if (WindowManagerService.DEBUG_FOCUS_LIGHT) Slog.i(TAG,
    399                             "setAnimationLocked: setting mFocusMayChange true");
    400                     mService.mFocusMayChange = true;
    401                 }
    402                 // Window is no longer visible -- make sure if we were waiting
    403                 // for it to be displayed before enabling the display, that
    404                 // we allow the display to be enabled now.
    405                 mService.enableScreenIfNeededLocked();
    406             }
    407         }
    408         mTransformation.clear();
    409         if (mDrawState == HAS_DRAWN
    410                 && mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING
    411                 && mWin.mAppToken != null
    412                 && mWin.mAppToken.firstWindowDrawn
    413                 && mWin.mAppToken.startingData != null) {
    414             if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Finish starting "
    415                     + mWin.mToken + ": first real window done animating");
    416             mService.mFinishedStarting.add(mWin.mAppToken);
    417             mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
    418         } else if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
    419             // Upon completion of a not-visible to visible status bar animation a relayout is
    420             // required.
    421             if (displayContent != null) {
    422                 displayContent.layoutNeeded = true;
    423             }
    424         }
    425 
    426         finishExit();
    427         final int displayId = mWin.getDisplayId();
    428         mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    429         if (WindowManagerService.DEBUG_LAYOUT_REPEATS) mService.debugLayoutRepeats(
    430                 "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));
    431 
    432         if (mWin.mAppToken != null) {
    433             mWin.mAppToken.updateReportedVisibilityLocked();
    434         }
    435 
    436         return false;
    437     }
    438 
    439     void finishExit() {
    440         if (WindowManagerService.DEBUG_ANIM) Slog.v(
    441                 TAG, "finishExit in " + this
    442                 + ": exiting=" + mWin.mExiting
    443                 + " remove=" + mWin.mRemoveOnExit
    444                 + " windowAnimating=" + isWindowAnimating());
    445 
    446         final int N = mWin.mChildWindows.size();
    447         for (int i=0; i<N; i++) {
    448             mWin.mChildWindows.get(i).mWinAnimator.finishExit();
    449         }
    450 
    451         if (mEnteringAnimation && mWin.mAppToken == null) {
    452             try {
    453                 mEnteringAnimation = false;
    454                 mWin.mClient.dispatchWindowShown();
    455             } catch (RemoteException e) {
    456             }
    457         }
    458 
    459         if (!isWindowAnimating()) {
    460             //TODO (multidisplay): Accessibility is supported only for the default display.
    461             if (mService.mAccessibilityController != null
    462                     && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
    463                 mService.mAccessibilityController.onSomeWindowResizedOrMovedLocked();
    464             }
    465         }
    466 
    467         if (!mWin.mExiting) {
    468             return;
    469         }
    470 
    471         if (isWindowAnimating()) {
    472             return;
    473         }
    474 
    475         if (WindowManagerService.localLOGV) Slog.v(
    476                 TAG, "Exit animation finished in " + this
    477                 + ": remove=" + mWin.mRemoveOnExit);
    478         if (mSurfaceControl != null) {
    479             mService.mDestroySurface.add(mWin);
    480             mWin.mDestroying = true;
    481             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(
    482                 mWin, "HIDE (finishExit)", null);
    483             hide();
    484         }
    485         mWin.mExiting = false;
    486         if (mWin.mRemoveOnExit) {
    487             mService.mPendingRemove.add(mWin);
    488             mWin.mRemoveOnExit = false;
    489         }
    490         mService.hideWallpapersLocked(mWin);
    491     }
    492 
    493     void hide() {
    494         if (!mLastHidden) {
    495             //dump();
    496             mLastHidden = true;
    497             if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
    498                     "HIDE (performLayout)", null);
    499             if (mSurfaceControl != null) {
    500                 mSurfaceShown = false;
    501                 try {
    502                     mSurfaceControl.hide();
    503                 } catch (RuntimeException e) {
    504                     Slog.w(TAG, "Exception hiding surface in " + mWin);
    505                 }
    506             }
    507         }
    508     }
    509 
    510     boolean finishDrawingLocked() {
    511         final boolean startingWindow =
    512                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
    513         if (DEBUG_STARTING_WINDOW && startingWindow) {
    514             Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
    515                     + drawStateToString());
    516         }
    517         if (mDrawState == DRAW_PENDING) {
    518             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
    519                 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + this + " in "
    520                         + mSurfaceControl);
    521             if (DEBUG_STARTING_WINDOW && startingWindow) {
    522                 Slog.v(TAG, "Draw state now committed in " + mWin);
    523             }
    524             mDrawState = COMMIT_DRAW_PENDING;
    525             return true;
    526         }
    527         return false;
    528     }
    529 
    530     // This must be called while inside a transaction.
    531     boolean commitFinishDrawingLocked() {
    532         if (DEBUG_STARTING_WINDOW &&
    533                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
    534             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
    535                     + drawStateToString());
    536         }
    537         if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
    538             return false;
    539         }
    540         if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
    541             Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceControl);
    542         }
    543         mDrawState = READY_TO_SHOW;
    544         final AppWindowToken atoken = mWin.mAppToken;
    545         if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
    546             return performShowLocked();
    547         }
    548         return false;
    549     }
    550 
    551     static class SurfaceTrace extends SurfaceControl {
    552         private final static String SURFACE_TAG = "SurfaceTrace";
    553         private final static boolean logSurfaceTrace = DEBUG_SURFACE_TRACE;
    554         final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
    555 
    556         private float mSurfaceTraceAlpha = 0;
    557         private int mLayer;
    558         private final PointF mPosition = new PointF();
    559         private final Point mSize = new Point();
    560         private final Rect mWindowCrop = new Rect();
    561         private boolean mShown = false;
    562         private int mLayerStack;
    563         private boolean mIsOpaque;
    564         private float mDsdx, mDtdx, mDsdy, mDtdy;
    565         private final String mName;
    566 
    567         public SurfaceTrace(SurfaceSession s,
    568                        String name, int w, int h, int format, int flags)
    569                    throws OutOfResourcesException {
    570             super(s, name, w, h, format, flags);
    571             mName = name != null ? name : "Not named";
    572             mSize.set(w, h);
    573             if (logSurfaceTrace) Slog.v(SURFACE_TAG, "ctor: " + this + ". Called by "
    574                     + Debug.getCallers(3));
    575             synchronized (sSurfaces) {
    576                 sSurfaces.add(0, this);
    577             }
    578         }
    579 
    580         @Override
    581         public void setAlpha(float alpha) {
    582             if (mSurfaceTraceAlpha != alpha) {
    583                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setAlpha(" + alpha + "): OLD:" + this +
    584                         ". Called by " + Debug.getCallers(3));
    585                 mSurfaceTraceAlpha = alpha;
    586             }
    587             super.setAlpha(alpha);
    588         }
    589 
    590         @Override
    591         public void setLayer(int zorder) {
    592             if (zorder != mLayer) {
    593                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setLayer(" + zorder + "): OLD:" + this
    594                         + ". Called by " + Debug.getCallers(3));
    595                 mLayer = zorder;
    596             }
    597             super.setLayer(zorder);
    598 
    599             synchronized (sSurfaces) {
    600                 sSurfaces.remove(this);
    601                 int i;
    602                 for (i = sSurfaces.size() - 1; i >= 0; i--) {
    603                     SurfaceTrace s = sSurfaces.get(i);
    604                     if (s.mLayer < zorder) {
    605                         break;
    606                     }
    607                 }
    608                 sSurfaces.add(i + 1, this);
    609             }
    610         }
    611 
    612         @Override
    613         public void setPosition(float x, float y) {
    614             if (x != mPosition.x || y != mPosition.y) {
    615                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setPosition(" + x + "," + y + "): OLD:"
    616                         + this + ". Called by " + Debug.getCallers(3));
    617                 mPosition.set(x, y);
    618             }
    619             super.setPosition(x, y);
    620         }
    621 
    622         @Override
    623         public void setSize(int w, int h) {
    624             if (w != mSize.x || h != mSize.y) {
    625                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
    626                         + this + ". Called by " + Debug.getCallers(3));
    627                 mSize.set(w, h);
    628             }
    629             super.setSize(w, h);
    630         }
    631 
    632         @Override
    633         public void setWindowCrop(Rect crop) {
    634             if (crop != null) {
    635                 if (!crop.equals(mWindowCrop)) {
    636                     if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setWindowCrop("
    637                             + crop.toShortString() + "): OLD:" + this + ". Called by "
    638                             + Debug.getCallers(3));
    639                     mWindowCrop.set(crop);
    640                 }
    641             }
    642             super.setWindowCrop(crop);
    643         }
    644 
    645         @Override
    646         public void setLayerStack(int layerStack) {
    647             if (layerStack != mLayerStack) {
    648                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setLayerStack(" + layerStack + "): OLD:"
    649                         + this + ". Called by " + Debug.getCallers(3));
    650                 mLayerStack = layerStack;
    651             }
    652             super.setLayerStack(layerStack);
    653         }
    654 
    655         @Override
    656         public void setOpaque(boolean isOpaque) {
    657             if (isOpaque != mIsOpaque) {
    658                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setOpaque(" + isOpaque + "): OLD:"
    659                         + this + ". Called by " + Debug.getCallers(3));
    660                 mIsOpaque = isOpaque;
    661             }
    662             super.setOpaque(isOpaque);
    663         }
    664 
    665         @Override
    666         public void setSecure(boolean isSecure) {
    667             super.setSecure(isSecure);
    668         }
    669 
    670         @Override
    671         public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
    672             if (dsdx != mDsdx || dtdx != mDtdx || dsdy != mDsdy || dtdy != mDtdy) {
    673                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "setMatrix(" + dsdx + "," + dtdx + ","
    674                         + dsdy + "," + dtdy + "): OLD:" + this + ". Called by "
    675                         + Debug.getCallers(3));
    676                 mDsdx = dsdx;
    677                 mDtdx = dtdx;
    678                 mDsdy = dsdy;
    679                 mDtdy = dtdy;
    680             }
    681             super.setMatrix(dsdx, dtdx, dsdy, dtdy);
    682         }
    683 
    684         @Override
    685         public void hide() {
    686             if (mShown) {
    687                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "hide: OLD:" + this + ". Called by "
    688                         + Debug.getCallers(3));
    689                 mShown = false;
    690             }
    691             super.hide();
    692         }
    693 
    694         @Override
    695         public void show() {
    696             if (!mShown) {
    697                 if (logSurfaceTrace) Slog.v(SURFACE_TAG, "show: OLD:" + this + ". Called by "
    698                         + Debug.getCallers(3));
    699                 mShown = true;
    700             }
    701             super.show();
    702         }
    703 
    704         @Override
    705         public void destroy() {
    706             super.destroy();
    707             if (logSurfaceTrace) Slog.v(SURFACE_TAG, "destroy: " + this + ". Called by "
    708                     + Debug.getCallers(3));
    709             synchronized (sSurfaces) {
    710                 sSurfaces.remove(this);
    711             }
    712         }
    713 
    714         @Override
    715         public void release() {
    716             super.release();
    717             if (logSurfaceTrace) Slog.v(SURFACE_TAG, "release: " + this + ". Called by "
    718                     + Debug.getCallers(3));
    719             synchronized (sSurfaces) {
    720                 sSurfaces.remove(this);
    721             }
    722         }
    723 
    724         static void dumpAllSurfaces(PrintWriter pw, String header) {
    725             synchronized (sSurfaces) {
    726                 final int N = sSurfaces.size();
    727                 if (N <= 0) {
    728                     return;
    729                 }
    730                 if (header != null) {
    731                     pw.println(header);
    732                 }
    733                 pw.println("WINDOW MANAGER SURFACES (dumpsys window surfaces)");
    734                 for (int i = 0; i < N; i++) {
    735                     SurfaceTrace s = sSurfaces.get(i);
    736                     pw.print("  Surface #"); pw.print(i); pw.print(": #");
    737                             pw.print(Integer.toHexString(System.identityHashCode(s)));
    738                             pw.print(" "); pw.println(s.mName);
    739                     pw.print("    mLayerStack="); pw.print(s.mLayerStack);
    740                             pw.print(" mLayer="); pw.println(s.mLayer);
    741                     pw.print("    mShown="); pw.print(s.mShown); pw.print(" mAlpha=");
    742                             pw.print(s.mSurfaceTraceAlpha); pw.print(" mIsOpaque=");
    743                             pw.println(s.mIsOpaque);
    744                     pw.print("    mPosition="); pw.print(s.mPosition.x); pw.print(",");
    745                             pw.print(s.mPosition.y);
    746                             pw.print(" mSize="); pw.print(s.mSize.x); pw.print("x");
    747                             pw.println(s.mSize.y);
    748                     pw.print("    mCrop="); s.mWindowCrop.printShortString(pw); pw.println();
    749                     pw.print("    Transform: ("); pw.print(s.mDsdx); pw.print(", ");
    750                             pw.print(s.mDtdx); pw.print(", "); pw.print(s.mDsdy);
    751                             pw.print(", "); pw.print(s.mDtdy); pw.println(")");
    752                 }
    753             }
    754         }
    755 
    756         @Override
    757         public String toString() {
    758             return "Surface " + Integer.toHexString(System.identityHashCode(this)) + " "
    759                     + mName + " (" + mLayerStack + "): shown=" + mShown + " layer=" + mLayer
    760                     + " alpha=" + mSurfaceTraceAlpha + " " + mPosition.x + "," + mPosition.y
    761                     + " " + mSize.x + "x" + mSize.y
    762                     + " crop=" + mWindowCrop.toShortString()
    763                     + " opaque=" + mIsOpaque
    764                     + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
    765         }
    766     }
    767 
    768     SurfaceControl createSurfaceLocked() {
    769         final WindowState w = mWin;
    770         if (mSurfaceControl == null) {
    771             if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
    772                     "createSurface " + this + ": mDrawState=DRAW_PENDING");
    773             mDrawState = DRAW_PENDING;
    774             if (w.mAppToken != null) {
    775                 if (w.mAppToken.mAppAnimator.animation == null) {
    776                     w.mAppToken.allDrawn = false;
    777                     w.mAppToken.deferClearAllDrawn = false;
    778                 } else {
    779                     // Currently animating, persist current state of allDrawn until animation
    780                     // is complete.
    781                     w.mAppToken.deferClearAllDrawn = true;
    782                 }
    783             }
    784 
    785             mService.makeWindowFreezingScreenIfNeededLocked(w);
    786 
    787             int flags = SurfaceControl.HIDDEN;
    788             final WindowManager.LayoutParams attrs = w.mAttrs;
    789 
    790             if (mService.isSecureLocked(w)) {
    791                 flags |= SurfaceControl.SECURE;
    792             }
    793 
    794             int width;
    795             int height;
    796             if ((attrs.flags & LayoutParams.FLAG_SCALED) != 0) {
    797                 // for a scaled surface, we always want the requested
    798                 // size.
    799                 width = w.mRequestedWidth;
    800                 height = w.mRequestedHeight;
    801             } else {
    802                 width = w.mCompatFrame.width();
    803                 height = w.mCompatFrame.height();
    804             }
    805 
    806             // Something is wrong and SurfaceFlinger will not like this,
    807             // try to revert to sane values
    808             if (width <= 0) {
    809                 width = 1;
    810             }
    811             if (height <= 0) {
    812                 height = 1;
    813             }
    814 
    815             float left = w.mFrame.left + w.mXOffset;
    816             float top = w.mFrame.top + w.mYOffset;
    817 
    818             // Adjust for surface insets.
    819             width += attrs.surfaceInsets.left + attrs.surfaceInsets.right;
    820             height += attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
    821             left -= attrs.surfaceInsets.left;
    822             top -= attrs.surfaceInsets.top;
    823 
    824             if (DEBUG_VISIBILITY) {
    825                 Slog.v(TAG, "Creating surface in session "
    826                         + mSession.mSurfaceSession + " window " + this
    827                         + " w=" + width + " h=" + height
    828                         + " x=" + left + " y=" + top
    829                         + " format=" + attrs.format + " flags=" + flags);
    830             }
    831 
    832             // We may abort, so initialize to defaults.
    833             mSurfaceShown = false;
    834             mSurfaceLayer = 0;
    835             mSurfaceAlpha = 0;
    836             mSurfaceX = 0;
    837             mSurfaceY = 0;
    838             w.mLastSystemDecorRect.set(0, 0, 0, 0);
    839             mHasClipRect = false;
    840             mClipRect.set(0, 0, 0, 0);
    841             mLastClipRect.set(0, 0, 0, 0);
    842 
    843             // Set up surface control with initial size.
    844             try {
    845                 mSurfaceW = width;
    846                 mSurfaceH = height;
    847 
    848                 final boolean isHwAccelerated = (attrs.flags &
    849                         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
    850                 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
    851                 if (!PixelFormat.formatHasAlpha(attrs.format)
    852                         && attrs.surfaceInsets.left == 0
    853                         && attrs.surfaceInsets.top == 0
    854                         && attrs.surfaceInsets.right == 0
    855                         && attrs.surfaceInsets.bottom  == 0) {
    856                     flags |= SurfaceControl.OPAQUE;
    857                 }
    858 
    859                 mSurfaceFormat = format;
    860                 if (DEBUG_SURFACE_TRACE) {
    861                     mSurfaceControl = new SurfaceTrace(
    862                             mSession.mSurfaceSession,
    863                             attrs.getTitle().toString(),
    864                             width, height, format, flags);
    865                 } else {
    866                     mSurfaceControl = new SurfaceControl(
    867                         mSession.mSurfaceSession,
    868                         attrs.getTitle().toString(),
    869                         width, height, format, flags);
    870                 }
    871 
    872                 w.mHasSurface = true;
    873 
    874                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    875                     Slog.i(TAG, "  CREATE SURFACE "
    876                             + mSurfaceControl + " IN SESSION "
    877                             + mSession.mSurfaceSession
    878                             + ": pid=" + mSession.mPid + " format="
    879                             + attrs.format + " flags=0x"
    880                             + Integer.toHexString(flags)
    881                             + " / " + this);
    882                 }
    883             } catch (OutOfResourcesException e) {
    884                 w.mHasSurface = false;
    885                 Slog.w(TAG, "OutOfResourcesException creating surface");
    886                 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
    887                 mDrawState = NO_SURFACE;
    888                 return null;
    889             } catch (Exception e) {
    890                 w.mHasSurface = false;
    891                 Slog.e(TAG, "Exception creating surface", e);
    892                 mDrawState = NO_SURFACE;
    893                 return null;
    894             }
    895 
    896             if (WindowManagerService.localLOGV) {
    897                 Slog.v(TAG, "Got surface: " + mSurfaceControl
    898                         + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
    899                         + ", animLayer=" + mAnimLayer);
    900             }
    901 
    902             if (SHOW_LIGHT_TRANSACTIONS) {
    903                 Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
    904                 WindowManagerService.logSurface(w, "CREATE pos=("
    905                         + w.mFrame.left + "," + w.mFrame.top + ") ("
    906                         + w.mCompatFrame.width() + "x" + w.mCompatFrame.height()
    907                         + "), layer=" + mAnimLayer + " HIDE", null);
    908             }
    909 
    910             // Start a new transaction and apply position & offset.
    911             SurfaceControl.openTransaction();
    912             try {
    913                 mSurfaceX = left;
    914                 mSurfaceY = top;
    915 
    916                 try {
    917                     mSurfaceControl.setPosition(left, top);
    918                     mSurfaceLayer = mAnimLayer;
    919                     final DisplayContent displayContent = w.getDisplayContent();
    920                     if (displayContent != null) {
    921                         mSurfaceControl.setLayerStack(displayContent.getDisplay().getLayerStack());
    922                     }
    923                     mSurfaceControl.setLayer(mAnimLayer);
    924                     mSurfaceControl.setAlpha(0);
    925                     mSurfaceShown = false;
    926                 } catch (RuntimeException e) {
    927                     Slog.w(TAG, "Error creating surface in " + w, e);
    928                     mService.reclaimSomeSurfaceMemoryLocked(this, "create-init", true);
    929                 }
    930                 mLastHidden = true;
    931             } finally {
    932                 SurfaceControl.closeTransaction();
    933                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
    934                         "<<< CLOSE TRANSACTION createSurfaceLocked");
    935             }
    936             if (WindowManagerService.localLOGV) Slog.v(
    937                     TAG, "Created surface " + this);
    938         }
    939         return mSurfaceControl;
    940     }
    941 
    942     void destroySurfaceLocked() {
    943         if (mWin.mAppToken != null && mWin == mWin.mAppToken.startingWindow) {
    944             mWin.mAppToken.startingDisplayed = false;
    945         }
    946 
    947         if (mSurfaceControl != null) {
    948 
    949             int i = mWin.mChildWindows.size();
    950             while (i > 0) {
    951                 i--;
    952                 WindowState c = mWin.mChildWindows.get(i);
    953                 c.mAttachedHidden = true;
    954             }
    955 
    956             try {
    957                 if (DEBUG_VISIBILITY) {
    958                     RuntimeException e = null;
    959                     if (!WindowManagerService.HIDE_STACK_CRAWLS) {
    960                         e = new RuntimeException();
    961                         e.fillInStackTrace();
    962                     }
    963                     Slog.w(TAG, "Window " + this + " destroying surface "
    964                             + mSurfaceControl + ", session " + mSession, e);
    965                 }
    966                 if (mSurfaceDestroyDeferred) {
    967                     if (mSurfaceControl != null && mPendingDestroySurface != mSurfaceControl) {
    968                         if (mPendingDestroySurface != null) {
    969                             if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    970                                 RuntimeException e = null;
    971                                 if (!WindowManagerService.HIDE_STACK_CRAWLS) {
    972                                     e = new RuntimeException();
    973                                     e.fillInStackTrace();
    974                                 }
    975                                 WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
    976                             }
    977                             mPendingDestroySurface.destroy();
    978                         }
    979                         mPendingDestroySurface = mSurfaceControl;
    980                     }
    981                 } else {
    982                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    983                         RuntimeException e = null;
    984                         if (!WindowManagerService.HIDE_STACK_CRAWLS) {
    985                             e = new RuntimeException();
    986                             e.fillInStackTrace();
    987                         }
    988                         WindowManagerService.logSurface(mWin, "DESTROY", e);
    989                     }
    990                     mSurfaceControl.destroy();
    991                 }
    992                 mService.hideWallpapersLocked(mWin);
    993             } catch (RuntimeException e) {
    994                 Slog.w(TAG, "Exception thrown when destroying Window " + this
    995                     + " surface " + mSurfaceControl + " session " + mSession
    996                     + ": " + e.toString());
    997             }
    998 
    999             mSurfaceShown = false;
   1000             mSurfaceControl = null;
   1001             mWin.mHasSurface = false;
   1002             mDrawState = NO_SURFACE;
   1003         }
   1004     }
   1005 
   1006     void destroyDeferredSurfaceLocked() {
   1007         try {
   1008             if (mPendingDestroySurface != null) {
   1009                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
   1010                     RuntimeException e = null;
   1011                     if (!WindowManagerService.HIDE_STACK_CRAWLS) {
   1012                         e = new RuntimeException();
   1013                         e.fillInStackTrace();
   1014                     }
   1015                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", e);
   1016                 }
   1017                 mPendingDestroySurface.destroy();
   1018                 mService.hideWallpapersLocked(mWin);
   1019             }
   1020         } catch (RuntimeException e) {
   1021             Slog.w(TAG, "Exception thrown when destroying Window "
   1022                     + this + " surface " + mPendingDestroySurface
   1023                     + " session " + mSession + ": " + e.toString());
   1024         }
   1025         mSurfaceDestroyDeferred = false;
   1026         mPendingDestroySurface = null;
   1027     }
   1028 
   1029     void computeShownFrameLocked() {
   1030         final boolean selfTransformation = mHasLocalTransformation;
   1031         Transformation attachedTransformation =
   1032                 (mAttachedWinAnimator != null && mAttachedWinAnimator.mHasLocalTransformation)
   1033                 ? mAttachedWinAnimator.mTransformation : null;
   1034         Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation)
   1035                 ? mAppAnimator.transformation : null;
   1036 
   1037         // Wallpapers are animated based on the "real" window they
   1038         // are currently targeting.
   1039         final WindowState wallpaperTarget = mService.mWallpaperTarget;
   1040         if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
   1041             final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
   1042             if (wallpaperAnimator.mHasLocalTransformation &&
   1043                     wallpaperAnimator.mAnimation != null &&
   1044                     !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
   1045                 attachedTransformation = wallpaperAnimator.mTransformation;
   1046                 if (WindowManagerService.DEBUG_WALLPAPER && attachedTransformation != null) {
   1047                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
   1048                 }
   1049             }
   1050             final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ?
   1051                     null : wallpaperTarget.mAppToken.mAppAnimator;
   1052                 if (wpAppAnimator != null && wpAppAnimator.hasTransformation
   1053                     && wpAppAnimator.animation != null
   1054                     && !wpAppAnimator.animation.getDetachWallpaper()) {
   1055                 appTransformation = wpAppAnimator.transformation;
   1056                 if (WindowManagerService.DEBUG_WALLPAPER && appTransformation != null) {
   1057                     Slog.v(TAG, "WP target app xform: " + appTransformation);
   1058                 }
   1059             }
   1060         }
   1061 
   1062         final int displayId = mWin.getDisplayId();
   1063         final ScreenRotationAnimation screenRotationAnimation =
   1064                 mAnimator.getScreenRotationAnimationLocked(displayId);
   1065         final boolean screenAnimation =
   1066                 screenRotationAnimation != null && screenRotationAnimation.isAnimating();
   1067         if (selfTransformation || attachedTransformation != null
   1068                 || appTransformation != null || screenAnimation) {
   1069             // cache often used attributes locally
   1070             final Rect frame = mWin.mFrame;
   1071             final float tmpFloats[] = mService.mTmpFloats;
   1072             final Matrix tmpMatrix = mWin.mTmpMatrix;
   1073 
   1074             // Compute the desired transformation.
   1075             if (screenAnimation && screenRotationAnimation.isRotating()) {
   1076                 // If we are doing a screen animation, the global rotation
   1077                 // applied to windows can result in windows that are carefully
   1078                 // aligned with each other to slightly separate, allowing you
   1079                 // to see what is behind them.  An unsightly mess.  This...
   1080                 // thing...  magically makes it call good: scale each window
   1081                 // slightly (two pixels larger in each dimension, from the
   1082                 // window's center).
   1083                 final float w = frame.width();
   1084                 final float h = frame.height();
   1085                 if (w>=1 && h>=1) {
   1086                     tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
   1087                 } else {
   1088                     tmpMatrix.reset();
   1089                 }
   1090             } else {
   1091                 tmpMatrix.reset();
   1092             }
   1093             tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
   1094             if (selfTransformation) {
   1095                 tmpMatrix.postConcat(mTransformation.getMatrix());
   1096             }
   1097             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
   1098             if (attachedTransformation != null) {
   1099                 tmpMatrix.postConcat(attachedTransformation.getMatrix());
   1100             }
   1101             if (appTransformation != null) {
   1102                 tmpMatrix.postConcat(appTransformation.getMatrix());
   1103             }
   1104             if (screenAnimation) {
   1105                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
   1106             }
   1107 
   1108             //TODO (multidisplay): Magnification is supported only for the default display.
   1109             if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
   1110                 MagnificationSpec spec = mService.mAccessibilityController
   1111                         .getMagnificationSpecForWindowLocked(mWin);
   1112                 if (spec != null && !spec.isNop()) {
   1113                     tmpMatrix.postScale(spec.scale, spec.scale);
   1114                     tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
   1115                 }
   1116             }
   1117 
   1118             // "convert" it into SurfaceFlinger's format
   1119             // (a 2x2 matrix + an offset)
   1120             // Here we must not transform the position of the surface
   1121             // since it is already included in the transformation.
   1122             //Slog.i(TAG, "Transform: " + matrix);
   1123 
   1124             mHaveMatrix = true;
   1125             tmpMatrix.getValues(tmpFloats);
   1126             mDsDx = tmpFloats[Matrix.MSCALE_X];
   1127             mDtDx = tmpFloats[Matrix.MSKEW_Y];
   1128             mDsDy = tmpFloats[Matrix.MSKEW_X];
   1129             mDtDy = tmpFloats[Matrix.MSCALE_Y];
   1130             float x = tmpFloats[Matrix.MTRANS_X];
   1131             float y = tmpFloats[Matrix.MTRANS_Y];
   1132             int w = frame.width();
   1133             int h = frame.height();
   1134             mWin.mShownFrame.set(x, y, x+w, y+h);
   1135 
   1136             // Now set the alpha...  but because our current hardware
   1137             // can't do alpha transformation on a non-opaque surface,
   1138             // turn it off if we are running an animation that is also
   1139             // transforming since it is more important to have that
   1140             // animation be smooth.
   1141             mShownAlpha = mAlpha;
   1142             mHasClipRect = false;
   1143             if (!mService.mLimitedAlphaCompositing
   1144                     || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
   1145                     || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDsDy, mDtDy)
   1146                             && x == frame.left && y == frame.top))) {
   1147                 //Slog.i(TAG, "Applying alpha transform");
   1148                 if (selfTransformation) {
   1149                     mShownAlpha *= mTransformation.getAlpha();
   1150                 }
   1151                 if (attachedTransformation != null) {
   1152                     mShownAlpha *= attachedTransformation.getAlpha();
   1153                 }
   1154                 if (appTransformation != null) {
   1155                     mShownAlpha *= appTransformation.getAlpha();
   1156                     if (appTransformation.hasClipRect()) {
   1157                         mClipRect.set(appTransformation.getClipRect());
   1158                         if (mWin.mHScale > 0) {
   1159                             mClipRect.left /= mWin.mHScale;
   1160                             mClipRect.right /= mWin.mHScale;
   1161                         }
   1162                         if (mWin.mVScale > 0) {
   1163                             mClipRect.top /= mWin.mVScale;
   1164                             mClipRect.bottom /= mWin.mVScale;
   1165                         }
   1166                         mHasClipRect = true;
   1167                     }
   1168                 }
   1169                 if (screenAnimation) {
   1170                     mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
   1171                 }
   1172             } else {
   1173                 //Slog.i(TAG, "Not applying alpha transform");
   1174             }
   1175 
   1176             if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
   1177                     && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
   1178                     TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
   1179                     + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
   1180                     + " attached=" + (attachedTransformation == null ?
   1181                             "null" : attachedTransformation.getAlpha())
   1182                     + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha())
   1183                     + " screen=" + (screenAnimation ?
   1184                             screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
   1185             return;
   1186         } else if (mIsWallpaper && mService.mInnerFields.mWallpaperActionPending) {
   1187             return;
   1188         }
   1189 
   1190         if (WindowManagerService.localLOGV) Slog.v(
   1191                 TAG, "computeShownFrameLocked: " + this +
   1192                 " not attached, mAlpha=" + mAlpha);
   1193 
   1194         MagnificationSpec spec = null;
   1195         //TODO (multidisplay): Magnification is supported only for the default display.
   1196         if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
   1197             spec = mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
   1198         }
   1199         if (spec != null) {
   1200             final Rect frame = mWin.mFrame;
   1201             final float tmpFloats[] = mService.mTmpFloats;
   1202             final Matrix tmpMatrix = mWin.mTmpMatrix;
   1203 
   1204             tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
   1205             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
   1206 
   1207             if (spec != null && !spec.isNop()) {
   1208                 tmpMatrix.postScale(spec.scale, spec.scale);
   1209                 tmpMatrix.postTranslate(spec.offsetX, spec.offsetY);
   1210             }
   1211 
   1212             tmpMatrix.getValues(tmpFloats);
   1213 
   1214             mHaveMatrix = true;
   1215             mDsDx = tmpFloats[Matrix.MSCALE_X];
   1216             mDtDx = tmpFloats[Matrix.MSKEW_Y];
   1217             mDsDy = tmpFloats[Matrix.MSKEW_X];
   1218             mDtDy = tmpFloats[Matrix.MSCALE_Y];
   1219             float x = tmpFloats[Matrix.MTRANS_X];
   1220             float y = tmpFloats[Matrix.MTRANS_Y];
   1221             int w = frame.width();
   1222             int h = frame.height();
   1223             mWin.mShownFrame.set(x, y, x + w, y + h);
   1224 
   1225             mShownAlpha = mAlpha;
   1226         } else {
   1227             mWin.mShownFrame.set(mWin.mFrame);
   1228             if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
   1229                 mWin.mShownFrame.offset(mWin.mXOffset, mWin.mYOffset);
   1230             }
   1231             mShownAlpha = mAlpha;
   1232             mHaveMatrix = false;
   1233             mDsDx = mWin.mGlobalScale;
   1234             mDtDx = 0;
   1235             mDsDy = 0;
   1236             mDtDy = mWin.mGlobalScale;
   1237         }
   1238     }
   1239 
   1240     private void applyDecorRect(final Rect decorRect) {
   1241         final WindowState w = mWin;
   1242         final int width = w.mFrame.width();
   1243         final int height = w.mFrame.height();
   1244 
   1245         // Compute the offset of the window in relation to the decor rect.
   1246         final int left = w.mXOffset + w.mFrame.left;
   1247         final int top = w.mYOffset + w.mFrame.top;
   1248 
   1249         // Initialize the decor rect to the entire frame.
   1250         w.mSystemDecorRect.set(0, 0, width, height);
   1251 
   1252         // Intersect with the decor rect, offsetted by window position.
   1253         w.mSystemDecorRect.intersect(decorRect.left - left, decorRect.top - top,
   1254                 decorRect.right - left, decorRect.bottom - top);
   1255 
   1256         // If size compatibility is being applied to the window, the
   1257         // surface is scaled relative to the screen.  Also apply this
   1258         // scaling to the crop rect.  We aren't using the standard rect
   1259         // scale function because we want to round things to make the crop
   1260         // always round to a larger rect to ensure we don't crop too
   1261         // much and hide part of the window that should be seen.
   1262         if (w.mEnforceSizeCompat && w.mInvGlobalScale != 1.0f) {
   1263             final float scale = w.mInvGlobalScale;
   1264             w.mSystemDecorRect.left = (int) (w.mSystemDecorRect.left * scale - 0.5f);
   1265             w.mSystemDecorRect.top = (int) (w.mSystemDecorRect.top * scale - 0.5f);
   1266             w.mSystemDecorRect.right = (int) ((w.mSystemDecorRect.right+1) * scale - 0.5f);
   1267             w.mSystemDecorRect.bottom = (int) ((w.mSystemDecorRect.bottom+1) * scale - 0.5f);
   1268         }
   1269     }
   1270 
   1271     void updateSurfaceWindowCrop(final boolean recoveringMemory) {
   1272         final WindowState w = mWin;
   1273         final DisplayContent displayContent = w.getDisplayContent();
   1274         if (displayContent == null) {
   1275             return;
   1276         }
   1277         final DisplayInfo displayInfo = displayContent.getDisplayInfo();
   1278 
   1279         // Need to recompute a new system decor rect each time.
   1280         if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
   1281             // Currently can't do this cropping for scaled windows.  We'll
   1282             // just keep the crop rect the same as the source surface.
   1283             w.mSystemDecorRect.set(0, 0, w.mRequestedWidth, w.mRequestedHeight);
   1284         } else if (!w.isDefaultDisplay()) {
   1285             // On a different display there is no system decor.  Crop the window
   1286             // by the screen boundaries.
   1287             w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
   1288             w.mSystemDecorRect.intersect(-w.mCompatFrame.left, -w.mCompatFrame.top,
   1289                     displayInfo.logicalWidth - w.mCompatFrame.left,
   1290                     displayInfo.logicalHeight - w.mCompatFrame.top);
   1291         } else if (w.mLayer >= mService.mSystemDecorLayer) {
   1292             // Above the decor layer is easy, just use the entire window.
   1293             w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
   1294         } else if (w.mDecorFrame.isEmpty()) {
   1295             // Windows without policy decor aren't cropped.
   1296             w.mSystemDecorRect.set(0, 0, w.mCompatFrame.width(), w.mCompatFrame.height());
   1297         } else if (w.mAttrs.type == LayoutParams.TYPE_WALLPAPER && mAnimator.mAnimating) {
   1298             // If we're animating, the wallpaper crop should only be updated at the end of the
   1299             // animation.
   1300             mTmpClipRect.set(w.mSystemDecorRect);
   1301             applyDecorRect(w.mDecorFrame);
   1302             w.mSystemDecorRect.union(mTmpClipRect);
   1303         } else {
   1304             // Crop to the system decor specified by policy.
   1305             applyDecorRect(w.mDecorFrame);
   1306         }
   1307 
   1308         final boolean fullscreen = w.isFullscreen(displayInfo.appWidth, displayInfo.appHeight);
   1309         final Rect clipRect = mTmpClipRect;
   1310         // We use the clip rect as provided by the tranformation for non-fullscreen windows to
   1311         // avoid premature clipping with the system decor rect.
   1312         clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : w.mSystemDecorRect);
   1313 
   1314         // Expand the clip rect for surface insets.
   1315         final WindowManager.LayoutParams attrs = w.mAttrs;
   1316         clipRect.left -= attrs.surfaceInsets.left;
   1317         clipRect.top -= attrs.surfaceInsets.top;
   1318         clipRect.right += attrs.surfaceInsets.right;
   1319         clipRect.bottom += attrs.surfaceInsets.bottom;
   1320 
   1321         if (mHasClipRect && fullscreen) {
   1322             // We intersect the clip rect specified by the transformation with the expanded system
   1323             // decor rect to prevent artifacts from drawing during animation if the transformation
   1324             // clip rect extends outside the system decor rect.
   1325             clipRect.intersect(mClipRect);
   1326         }
   1327 
   1328         // The clip rect was generated assuming (0,0) as the window origin,
   1329         // so we need to translate to match the actual surface coordinates.
   1330         clipRect.offset(attrs.surfaceInsets.left, attrs.surfaceInsets.top);
   1331 
   1332         if (!clipRect.equals(mLastClipRect)) {
   1333             mLastClipRect.set(clipRect);
   1334             try {
   1335                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1336                         "CROP " + clipRect.toShortString(), null);
   1337                 mSurfaceControl.setWindowCrop(clipRect);
   1338             } catch (RuntimeException e) {
   1339                 Slog.w(TAG, "Error setting crop surface of " + w
   1340                         + " crop=" + clipRect.toShortString(), e);
   1341                 if (!recoveringMemory) {
   1342                     mService.reclaimSomeSurfaceMemoryLocked(this, "crop", true);
   1343                 }
   1344             }
   1345         }
   1346     }
   1347 
   1348     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
   1349         final WindowState w = mWin;
   1350 
   1351         int width;
   1352         int height;
   1353         if ((w.mAttrs.flags & LayoutParams.FLAG_SCALED) != 0) {
   1354             // for a scaled surface, we always want the requested
   1355             // size.
   1356             width  = w.mRequestedWidth;
   1357             height = w.mRequestedHeight;
   1358         } else {
   1359             width = w.mCompatFrame.width();
   1360             height = w.mCompatFrame.height();
   1361         }
   1362 
   1363         // Something is wrong and SurfaceFlinger will not like this,
   1364         // try to revert to sane values
   1365         if (width < 1) {
   1366             width = 1;
   1367         }
   1368         if (height < 1) {
   1369             height = 1;
   1370         }
   1371 
   1372         float left = w.mShownFrame.left;
   1373         float top = w.mShownFrame.top;
   1374 
   1375         // Adjust for surface insets.
   1376         final LayoutParams attrs = w.getAttrs();
   1377         final int displayId = w.getDisplayId();
   1378         float scale = 1.0f;
   1379         // Magnification is supported only for the default display.
   1380         if (mService.mAccessibilityController != null && displayId == Display.DEFAULT_DISPLAY) {
   1381             MagnificationSpec spec =
   1382                     mService.mAccessibilityController.getMagnificationSpecForWindowLocked(w);
   1383             if (spec != null && !spec.isNop()) {
   1384                 scale = spec.scale;
   1385             }
   1386         }
   1387 
   1388         width += scale * (attrs.surfaceInsets.left + attrs.surfaceInsets.right);
   1389         height += scale * (attrs.surfaceInsets.top + attrs.surfaceInsets.bottom);
   1390         left -= scale * attrs.surfaceInsets.left;
   1391         top -= scale * attrs.surfaceInsets.top;
   1392 
   1393         final boolean surfaceMoved = mSurfaceX != left || mSurfaceY != top;
   1394         if (surfaceMoved) {
   1395             mSurfaceX = left;
   1396             mSurfaceY = top;
   1397 
   1398             try {
   1399                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1400                         "POS " + left + ", " + top, null);
   1401                 mSurfaceControl.setPosition(left, top);
   1402             } catch (RuntimeException e) {
   1403                 Slog.w(TAG, "Error positioning surface of " + w
   1404                         + " pos=(" + left + "," + top + ")", e);
   1405                 if (!recoveringMemory) {
   1406                     mService.reclaimSomeSurfaceMemoryLocked(this, "position", true);
   1407                 }
   1408             }
   1409         }
   1410 
   1411         final boolean surfaceResized = mSurfaceW != width || mSurfaceH != height;
   1412         if (surfaceResized) {
   1413             mSurfaceW = width;
   1414             mSurfaceH = height;
   1415             mSurfaceResized = true;
   1416 
   1417             try {
   1418                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1419                         "SIZE " + width + "x" + height, null);
   1420                 mSurfaceControl.setSize(width, height);
   1421                 mSurfaceControl.setMatrix(
   1422                         mDsDx * w.mHScale, mDtDx * w.mVScale,
   1423                         mDsDy * w.mHScale, mDtDy * w.mVScale);
   1424                 mAnimator.setPendingLayoutChanges(w.getDisplayId(),
   1425                         WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
   1426                 if ((w.mAttrs.flags & LayoutParams.FLAG_DIM_BEHIND) != 0) {
   1427                     final TaskStack stack = w.getStack();
   1428                     if (stack != null) {
   1429                         stack.startDimmingIfNeeded(this);
   1430                     }
   1431                 }
   1432             } catch (RuntimeException e) {
   1433                 // If something goes wrong with the surface (such
   1434                 // as running out of memory), don't take down the
   1435                 // entire system.
   1436                 Slog.e(TAG, "Error resizing surface of " + w
   1437                         + " size=(" + width + "x" + height + ")", e);
   1438                 if (!recoveringMemory) {
   1439                     mService.reclaimSomeSurfaceMemoryLocked(this, "size", true);
   1440                 }
   1441             }
   1442         }
   1443 
   1444         updateSurfaceWindowCrop(recoveringMemory);
   1445     }
   1446 
   1447     public void prepareSurfaceLocked(final boolean recoveringMemory) {
   1448         final WindowState w = mWin;
   1449         if (mSurfaceControl == null) {
   1450             if (w.mOrientationChanging) {
   1451                 if (DEBUG_ORIENTATION) {
   1452                     Slog.v(TAG, "Orientation change skips hidden " + w);
   1453                 }
   1454                 w.mOrientationChanging = false;
   1455             }
   1456             return;
   1457         }
   1458 
   1459         boolean displayed = false;
   1460 
   1461         computeShownFrameLocked();
   1462 
   1463         setSurfaceBoundariesLocked(recoveringMemory);
   1464 
   1465         if (mIsWallpaper && !mWin.mWallpaperVisible) {
   1466             // Wallpaper is no longer visible and there is no wp target => hide it.
   1467             hide();
   1468         } else if (w.mAttachedHidden || !w.isOnScreen()) {
   1469             hide();
   1470             mService.hideWallpapersLocked(w);
   1471 
   1472             // If we are waiting for this window to handle an
   1473             // orientation change, well, it is hidden, so
   1474             // doesn't really matter.  Note that this does
   1475             // introduce a potential glitch if the window
   1476             // becomes unhidden before it has drawn for the
   1477             // new orientation.
   1478             if (w.mOrientationChanging) {
   1479                 w.mOrientationChanging = false;
   1480                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   1481                         "Orientation change skips hidden " + w);
   1482             }
   1483         } else if (mLastLayer != mAnimLayer
   1484                 || mLastAlpha != mShownAlpha
   1485                 || mLastDsDx != mDsDx
   1486                 || mLastDtDx != mDtDx
   1487                 || mLastDsDy != mDsDy
   1488                 || mLastDtDy != mDtDy
   1489                 || w.mLastHScale != w.mHScale
   1490                 || w.mLastVScale != w.mVScale
   1491                 || mLastHidden) {
   1492             displayed = true;
   1493             mLastAlpha = mShownAlpha;
   1494             mLastLayer = mAnimLayer;
   1495             mLastDsDx = mDsDx;
   1496             mLastDtDx = mDtDx;
   1497             mLastDsDy = mDsDy;
   1498             mLastDtDy = mDtDy;
   1499             w.mLastHScale = w.mHScale;
   1500             w.mLastVScale = w.mVScale;
   1501             if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1502                     "alpha=" + mShownAlpha + " layer=" + mAnimLayer
   1503                     + " matrix=[" + mDsDx + "*" + w.mHScale
   1504                     + "," + mDtDx + "*" + w.mVScale
   1505                     + "][" + mDsDy + "*" + w.mHScale
   1506                     + "," + mDtDy + "*" + w.mVScale + "]", null);
   1507             if (mSurfaceControl != null) {
   1508                 try {
   1509                     mSurfaceAlpha = mShownAlpha;
   1510                     mSurfaceControl.setAlpha(mShownAlpha);
   1511                     mSurfaceLayer = mAnimLayer;
   1512                     mSurfaceControl.setLayer(mAnimLayer);
   1513                     mSurfaceControl.setMatrix(
   1514                             mDsDx * w.mHScale, mDtDx * w.mVScale,
   1515                             mDsDy * w.mHScale, mDtDy * w.mVScale);
   1516 
   1517                     if (mLastHidden && mDrawState == HAS_DRAWN) {
   1518                         if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1519                                 "SHOW (performLayout)", null);
   1520                         if (WindowManagerService.DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + w
   1521                                 + " during relayout");
   1522                         if (showSurfaceRobustlyLocked()) {
   1523                             mLastHidden = false;
   1524                             if (mIsWallpaper) {
   1525                                 mService.dispatchWallpaperVisibility(w, true);
   1526                             }
   1527                             // This draw means the difference between unique content and mirroring.
   1528                             // Run another pass through performLayout to set mHasContent in the
   1529                             // LogicalDisplay.
   1530                             mAnimator.setPendingLayoutChanges(w.getDisplayId(),
   1531                                     WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
   1532                         } else {
   1533                             w.mOrientationChanging = false;
   1534                         }
   1535                     }
   1536                     if (mSurfaceControl != null) {
   1537                         w.mToken.hasVisible = true;
   1538                     }
   1539                 } catch (RuntimeException e) {
   1540                     Slog.w(TAG, "Error updating surface in " + w, e);
   1541                     if (!recoveringMemory) {
   1542                         mService.reclaimSomeSurfaceMemoryLocked(this, "update", true);
   1543                     }
   1544                 }
   1545             }
   1546         } else {
   1547             if (DEBUG_ANIM && isAnimating()) {
   1548                 Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
   1549             }
   1550             displayed = true;
   1551         }
   1552 
   1553         if (displayed) {
   1554             if (w.mOrientationChanging) {
   1555                 if (!w.isDrawnLw()) {
   1556                     mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
   1557                     mAnimator.mLastWindowFreezeSource = w;
   1558                     if (DEBUG_ORIENTATION) Slog.v(TAG,
   1559                             "Orientation continue waiting for draw in " + w);
   1560                 } else {
   1561                     w.mOrientationChanging = false;
   1562                     if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w);
   1563                 }
   1564             }
   1565             w.mToken.hasVisible = true;
   1566         }
   1567     }
   1568 
   1569     void setTransparentRegionHintLocked(final Region region) {
   1570         if (mSurfaceControl == null) {
   1571             Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
   1572             return;
   1573         }
   1574         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setTransparentRegion");
   1575         SurfaceControl.openTransaction();
   1576         try {
   1577             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
   1578                     "transparentRegionHint=" + region, null);
   1579             mSurfaceControl.setTransparentRegionHint(region);
   1580         } finally {
   1581             SurfaceControl.closeTransaction();
   1582             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
   1583                     "<<< CLOSE TRANSACTION setTransparentRegion");
   1584         }
   1585     }
   1586 
   1587     void setWallpaperOffset(RectF shownFrame) {
   1588         final LayoutParams attrs = mWin.getAttrs();
   1589         final int left = ((int) shownFrame.left) - attrs.surfaceInsets.left;
   1590         final int top = ((int) shownFrame.top) - attrs.surfaceInsets.top;
   1591         if (mSurfaceX != left || mSurfaceY != top) {
   1592             if (mAnimating) {
   1593                 // If this window (or its app token) is animating, then the position
   1594                 // of the surface will be re-computed on the next animation frame.
   1595                 // We can't poke it directly here because it depends on whatever
   1596                 // transformation is being applied by the animation.
   1597                 return;
   1598             }
   1599             mSurfaceX = left;
   1600             mSurfaceY = top;
   1601             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
   1602             SurfaceControl.openTransaction();
   1603             try {
   1604                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
   1605                         "POS " + left + ", " + top, null);
   1606                 mSurfaceControl.setPosition(mWin.mFrame.left + left, mWin.mFrame.top + top);
   1607                 updateSurfaceWindowCrop(false);
   1608             } catch (RuntimeException e) {
   1609                 Slog.w(TAG, "Error positioning surface of " + mWin
   1610                         + " pos=(" + left + "," + top + ")", e);
   1611             } finally {
   1612                 SurfaceControl.closeTransaction();
   1613                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
   1614                         "<<< CLOSE TRANSACTION setWallpaperOffset");
   1615             }
   1616         }
   1617     }
   1618 
   1619     /**
   1620      * Try to change the pixel format without recreating the surface. This
   1621      * will be common in the case of changing from PixelFormat.OPAQUE to
   1622      * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
   1623      * requested formats resolve to the same underlying SurfaceControl format
   1624      * @return True if format was succesfully changed, false otherwise
   1625      */
   1626     boolean tryChangeFormatInPlaceLocked() {
   1627         if (mSurfaceControl == null) {
   1628             return false;
   1629         }
   1630         final LayoutParams attrs = mWin.getAttrs();
   1631         final boolean isHwAccelerated = (attrs.flags &
   1632                 WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
   1633         final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
   1634         if (format == mSurfaceFormat) {
   1635             setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
   1636             return true;
   1637         }
   1638         return false;
   1639     }
   1640 
   1641     void setOpaqueLocked(boolean isOpaque) {
   1642         if (mSurfaceControl == null) {
   1643             return;
   1644         }
   1645         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setOpaqueLocked");
   1646         SurfaceControl.openTransaction();
   1647         try {
   1648             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isOpaque=" + isOpaque,
   1649                     null);
   1650             mSurfaceControl.setOpaque(isOpaque);
   1651         } finally {
   1652             SurfaceControl.closeTransaction();
   1653             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setOpaqueLocked");
   1654         }
   1655     }
   1656 
   1657     void setSecureLocked(boolean isSecure) {
   1658         if (mSurfaceControl == null) {
   1659             return;
   1660         }
   1661         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setSecureLocked");
   1662         SurfaceControl.openTransaction();
   1663         try {
   1664             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "isSecure=" + isSecure,
   1665                     null);
   1666             mSurfaceControl.setSecure(isSecure);
   1667         } finally {
   1668             SurfaceControl.closeTransaction();
   1669             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION setSecureLocked");
   1670         }
   1671     }
   1672 
   1673     // This must be called while inside a transaction.
   1674     boolean performShowLocked() {
   1675         if (mWin.isHiddenFromUserLocked()) {
   1676             if (DEBUG_VISIBILITY) Slog.w(TAG, "hiding " + mWin + ", belonging to " + mWin.mOwnerUid);
   1677             mWin.hideLw(false);
   1678             return false;
   1679         }
   1680         if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
   1681                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
   1682             Slog.v(TAG, "performShow on " + this
   1683                     + ": mDrawState=" + drawStateToString() + " readyForDisplay="
   1684                     + mWin.isReadyForDisplayIgnoringKeyguard()
   1685                     + " starting=" + (mWin.mAttrs.type == TYPE_APPLICATION_STARTING)
   1686                     + " during animation: policyVis=" + mWin.mPolicyVisibility
   1687                     + " attHidden=" + mWin.mAttachedHidden
   1688                     + " tok.hiddenRequested="
   1689                     + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
   1690                     + " tok.hidden="
   1691                     + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
   1692                     + " animating=" + mAnimating
   1693                     + " tok animating="
   1694                     + (mAppAnimator != null ? mAppAnimator.animating : false) + " Callers="
   1695                     + Debug.getCallers(3));
   1696         }
   1697         if (mDrawState == READY_TO_SHOW && mWin.isReadyForDisplayIgnoringKeyguard()) {
   1698             if (SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
   1699                 WindowManagerService.logSurface(mWin, "SHOW (performShowLocked)", null);
   1700             if (DEBUG_VISIBILITY || (DEBUG_STARTING_WINDOW &&
   1701                     mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING)) {
   1702                 Slog.v(TAG, "Showing " + this
   1703                         + " during animation: policyVis=" + mWin.mPolicyVisibility
   1704                         + " attHidden=" + mWin.mAttachedHidden
   1705                         + " tok.hiddenRequested="
   1706                         + (mWin.mAppToken != null ? mWin.mAppToken.hiddenRequested : false)
   1707                         + " tok.hidden="
   1708                         + (mWin.mAppToken != null ? mWin.mAppToken.hidden : false)
   1709                         + " animating=" + mAnimating
   1710                         + " tok animating="
   1711                         + (mAppAnimator != null ? mAppAnimator.animating : false));
   1712             }
   1713 
   1714             mService.enableScreenIfNeededLocked();
   1715 
   1716             applyEnterAnimationLocked();
   1717 
   1718             // Force the show in the next prepareSurfaceLocked() call.
   1719             mLastAlpha = -1;
   1720             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM)
   1721                 Slog.v(TAG, "performShowLocked: mDrawState=HAS_DRAWN in " + this);
   1722             mDrawState = HAS_DRAWN;
   1723             mService.scheduleAnimationLocked();
   1724 
   1725             int i = mWin.mChildWindows.size();
   1726             while (i > 0) {
   1727                 i--;
   1728                 WindowState c = mWin.mChildWindows.get(i);
   1729                 if (c.mAttachedHidden) {
   1730                     c.mAttachedHidden = false;
   1731                     if (c.mWinAnimator.mSurfaceControl != null) {
   1732                         c.mWinAnimator.performShowLocked();
   1733                         // It hadn't been shown, which means layout not
   1734                         // performed on it, so now we want to make sure to
   1735                         // do a layout.  If called from within the transaction
   1736                         // loop, this will cause it to restart with a new
   1737                         // layout.
   1738                         final DisplayContent displayContent = c.getDisplayContent();
   1739                         if (displayContent != null) {
   1740                             displayContent.layoutNeeded = true;
   1741                         }
   1742                     }
   1743                 }
   1744             }
   1745 
   1746             if (mWin.mAttrs.type != TYPE_APPLICATION_STARTING
   1747                     && mWin.mAppToken != null) {
   1748                 mWin.mAppToken.firstWindowDrawn = true;
   1749 
   1750                 if (mWin.mAppToken.startingData != null) {
   1751                     if (WindowManagerService.DEBUG_STARTING_WINDOW ||
   1752                             WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
   1753                             "Finish starting " + mWin.mToken
   1754                             + ": first real window is shown, no animation");
   1755                     // If this initial window is animating, stop it -- we
   1756                     // will do an animation to reveal it from behind the
   1757                     // starting window, so there is no need for it to also
   1758                     // be doing its own stuff.
   1759                     clearAnimation();
   1760                     mService.mFinishedStarting.add(mWin.mAppToken);
   1761                     mService.mH.sendEmptyMessage(H.FINISHED_STARTING);
   1762                 }
   1763                 mWin.mAppToken.updateReportedVisibilityLocked();
   1764             }
   1765 
   1766             return true;
   1767         }
   1768 
   1769         return false;
   1770     }
   1771 
   1772     /**
   1773      * Have the surface flinger show a surface, robustly dealing with
   1774      * error conditions.  In particular, if there is not enough memory
   1775      * to show the surface, then we will try to get rid of other surfaces
   1776      * in order to succeed.
   1777      *
   1778      * @return Returns true if the surface was successfully shown.
   1779      */
   1780     boolean showSurfaceRobustlyLocked() {
   1781         try {
   1782             if (mSurfaceControl != null) {
   1783                 mSurfaceShown = true;
   1784                 mSurfaceControl.show();
   1785                 if (mWin.mTurnOnScreen) {
   1786                     if (DEBUG_VISIBILITY) Slog.v(TAG,
   1787                             "Show surface turning screen on: " + mWin);
   1788                     mWin.mTurnOnScreen = false;
   1789                     mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
   1790                 }
   1791             }
   1792             return true;
   1793         } catch (RuntimeException e) {
   1794             Slog.w(TAG, "Failure showing surface " + mSurfaceControl + " in " + mWin, e);
   1795         }
   1796 
   1797         mService.reclaimSomeSurfaceMemoryLocked(this, "show", true);
   1798 
   1799         return false;
   1800     }
   1801 
   1802     void applyEnterAnimationLocked() {
   1803         final int transit;
   1804         if (mEnterAnimationPending) {
   1805             mEnterAnimationPending = false;
   1806             transit = WindowManagerPolicy.TRANSIT_ENTER;
   1807         } else {
   1808             transit = WindowManagerPolicy.TRANSIT_SHOW;
   1809         }
   1810         applyAnimationLocked(transit, true);
   1811         //TODO (multidisplay): Magnification is supported only for the default display.
   1812         if (mService.mAccessibilityController != null
   1813                 && mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
   1814             mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit);
   1815         }
   1816     }
   1817 
   1818     /**
   1819      * Choose the correct animation and set it to the passed WindowState.
   1820      * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn
   1821      *      then the animation will be app_starting_exit. Any other value loads the animation from
   1822      *      the switch statement below.
   1823      * @param isEntrance The animation type the last time this was called. Used to keep from
   1824      *      loading the same animation twice.
   1825      * @return true if an animation has been loaded.
   1826      */
   1827     boolean applyAnimationLocked(int transit, boolean isEntrance) {
   1828         if ((mLocalAnimating && mAnimationIsEntrance == isEntrance)
   1829                 || mKeyguardGoingAwayAnimation) {
   1830             // If we are trying to apply an animation, but already running
   1831             // an animation of the same type, then just leave that one alone.
   1832 
   1833             // If we are in a keyguard exit animation, and the window should animate away, modify
   1834             // keyguard exit animation such that it also fades out.
   1835             if (mAnimation != null && mKeyguardGoingAwayAnimation
   1836                     && transit == WindowManagerPolicy.TRANSIT_PREVIEW_DONE) {
   1837                 applyFadeoutDuringKeyguardExitAnimation();
   1838             }
   1839             return true;
   1840         }
   1841 
   1842         // Only apply an animation if the display isn't frozen.  If it is
   1843         // frozen, there is no reason to animate and it can cause strange
   1844         // artifacts when we unfreeze the display if some different animation
   1845         // is running.
   1846         if (mService.okToDisplay()) {
   1847             int anim = mPolicy.selectAnimationLw(mWin, transit);
   1848             int attr = -1;
   1849             Animation a = null;
   1850             if (anim != 0) {
   1851                 a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
   1852             } else {
   1853                 switch (transit) {
   1854                     case WindowManagerPolicy.TRANSIT_ENTER:
   1855                         attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
   1856                         break;
   1857                     case WindowManagerPolicy.TRANSIT_EXIT:
   1858                         attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
   1859                         break;
   1860                     case WindowManagerPolicy.TRANSIT_SHOW:
   1861                         attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
   1862                         break;
   1863                     case WindowManagerPolicy.TRANSIT_HIDE:
   1864                         attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
   1865                         break;
   1866                 }
   1867                 if (attr >= 0) {
   1868                     a = mService.mAppTransition.loadAnimationAttr(mWin.mAttrs, attr);
   1869                 }
   1870             }
   1871             if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
   1872                     "applyAnimation: win=" + this
   1873                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
   1874                     + " a=" + a
   1875                     + " transit=" + transit
   1876                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
   1877             if (a != null) {
   1878                 if (WindowManagerService.DEBUG_ANIM) {
   1879                     RuntimeException e = null;
   1880                     if (!WindowManagerService.HIDE_STACK_CRAWLS) {
   1881                         e = new RuntimeException();
   1882                         e.fillInStackTrace();
   1883                     }
   1884                     Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
   1885                 }
   1886                 setAnimation(a);
   1887                 mAnimationIsEntrance = isEntrance;
   1888             }
   1889         } else {
   1890             clearAnimation();
   1891         }
   1892 
   1893         return mAnimation != null;
   1894     }
   1895 
   1896     private void applyFadeoutDuringKeyguardExitAnimation() {
   1897         long startTime = mAnimation.getStartTime();
   1898         long duration = mAnimation.getDuration();
   1899         long elapsed = mLastAnimationTime - startTime;
   1900         long fadeDuration = duration - elapsed;
   1901         if (fadeDuration <= 0) {
   1902             // Never mind, this would be no visible animation, so abort the animation change.
   1903             return;
   1904         }
   1905         AnimationSet newAnimation = new AnimationSet(false /* shareInterpolator */);
   1906         newAnimation.setDuration(duration);
   1907         newAnimation.setStartTime(startTime);
   1908         newAnimation.addAnimation(mAnimation);
   1909         Animation fadeOut = AnimationUtils.loadAnimation(
   1910                 mContext, com.android.internal.R.anim.app_starting_exit);
   1911         fadeOut.setDuration(fadeDuration);
   1912         fadeOut.setStartOffset(elapsed);
   1913         newAnimation.addAnimation(fadeOut);
   1914         newAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDw, mAnimDh);
   1915         mAnimation = newAnimation;
   1916     }
   1917 
   1918     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
   1919         if (mAnimating || mLocalAnimating || mAnimationIsEntrance
   1920                 || mAnimation != null) {
   1921             pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
   1922                     pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
   1923                     pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
   1924                     pw.print(" mAnimation="); pw.println(mAnimation);
   1925         }
   1926         if (mHasTransformation || mHasLocalTransformation) {
   1927             pw.print(prefix); pw.print("XForm: has=");
   1928                     pw.print(mHasTransformation);
   1929                     pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
   1930                     pw.print(" "); mTransformation.printShortString(pw);
   1931                     pw.println();
   1932         }
   1933         if (mSurfaceControl != null) {
   1934             if (dumpAll) {
   1935                 pw.print(prefix); pw.print("mSurface="); pw.println(mSurfaceControl);
   1936                 pw.print(prefix); pw.print("mDrawState=");
   1937                 pw.print(drawStateToString());
   1938                 pw.print(" mLastHidden="); pw.println(mLastHidden);
   1939             }
   1940             pw.print(prefix); pw.print("Surface: shown="); pw.print(mSurfaceShown);
   1941                     pw.print(" layer="); pw.print(mSurfaceLayer);
   1942                     pw.print(" alpha="); pw.print(mSurfaceAlpha);
   1943                     pw.print(" rect=("); pw.print(mSurfaceX);
   1944                     pw.print(","); pw.print(mSurfaceY);
   1945                     pw.print(") "); pw.print(mSurfaceW);
   1946                     pw.print(" x "); pw.println(mSurfaceH);
   1947         }
   1948         if (mPendingDestroySurface != null) {
   1949             pw.print(prefix); pw.print("mPendingDestroySurface=");
   1950                     pw.println(mPendingDestroySurface);
   1951         }
   1952         if (mSurfaceResized || mSurfaceDestroyDeferred) {
   1953             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
   1954                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
   1955         }
   1956         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
   1957             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
   1958                     pw.print(" mAlpha="); pw.print(mAlpha);
   1959                     pw.print(" mLastAlpha="); pw.println(mLastAlpha);
   1960         }
   1961         if (mHaveMatrix || mWin.mGlobalScale != 1) {
   1962             pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
   1963                     pw.print(" mDsDx="); pw.print(mDsDx);
   1964                     pw.print(" mDtDx="); pw.print(mDtDx);
   1965                     pw.print(" mDsDy="); pw.print(mDsDy);
   1966                     pw.print(" mDtDy="); pw.println(mDtDy);
   1967         }
   1968     }
   1969 
   1970     @Override
   1971     public String toString() {
   1972         StringBuffer sb = new StringBuffer("WindowStateAnimator{");
   1973         sb.append(Integer.toHexString(System.identityHashCode(this)));
   1974         sb.append(' ');
   1975         sb.append(mWin.mAttrs.getTitle());
   1976         sb.append('}');
   1977         return sb.toString();
   1978     }
   1979 }
   1980