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.app.ActivityManager.StackId;
     20 import static android.view.Display.DEFAULT_DISPLAY;
     21 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
     22 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
     23 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
     24 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
     25 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
     26 import static com.android.server.wm.AppWindowAnimator.sDummyAnimation;
     27 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
     28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
     29 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYERS;
     30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
     31 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
     32 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW;
     33 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
     34 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SURFACE_TRACE;
     35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
     36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER;
     37 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
     38 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
     39 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
     40 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
     41 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
     42 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
     43 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
     44 import static com.android.server.wm.WindowManagerService.localLOGV;
     45 import static com.android.server.wm.WindowManagerService.logWithStack;
     46 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
     47 import static com.android.server.wm.WindowSurfacePlacer.SET_TURN_ON_SCREEN;
     48 
     49 import android.content.Context;
     50 import android.graphics.Matrix;
     51 import android.graphics.PixelFormat;
     52 import android.graphics.Point;
     53 import android.graphics.Rect;
     54 import android.graphics.RectF;
     55 import android.graphics.Region;
     56 import android.os.Debug;
     57 import android.os.Trace;
     58 import android.util.Slog;
     59 import android.view.DisplayInfo;
     60 import android.view.MagnificationSpec;
     61 import android.view.Surface.OutOfResourcesException;
     62 import android.view.SurfaceControl;
     63 import android.view.WindowManager;
     64 import android.view.WindowManager.LayoutParams;
     65 import android.view.WindowManagerPolicy;
     66 import android.view.animation.Animation;
     67 import android.view.animation.AnimationSet;
     68 import android.view.animation.AnimationUtils;
     69 import android.view.animation.Transformation;
     70 
     71 import java.io.PrintWriter;
     72 import java.io.FileDescriptor;
     73 
     74 /**
     75  * Keep track of animations and surface operations for a single WindowState.
     76  **/
     77 class WindowStateAnimator {
     78     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
     79     static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
     80 
     81     /**
     82      * Mode how the window gets clipped by the stack bounds during an animation: The clipping should
     83      * be applied after applying the animation transformation, i.e. the stack bounds don't move
     84      * during the animation.
     85      */
     86     static final int STACK_CLIP_AFTER_ANIM = 0;
     87 
     88     /**
     89      * Mode how the window gets clipped by the stack bounds: The clipping should be applied before
     90      * applying the animation transformation, i.e. the stack bounds move with the window.
     91      */
     92     static final int STACK_CLIP_BEFORE_ANIM = 1;
     93 
     94     /**
     95      * Mode how window gets clipped by the stack bounds during an animation: Don't clip the window
     96      * by the stack bounds.
     97      */
     98     static final int STACK_CLIP_NONE = 2;
     99 
    100     // Unchanging local convenience fields.
    101     final WindowManagerService mService;
    102     final WindowState mWin;
    103     private final WindowStateAnimator mParentWinAnimator;
    104     final WindowAnimator mAnimator;
    105     AppWindowAnimator mAppAnimator;
    106     final Session mSession;
    107     final WindowManagerPolicy mPolicy;
    108     final Context mContext;
    109     final boolean mIsWallpaper;
    110     private final WallpaperController mWallpaperControllerLocked;
    111 
    112     // Currently running animation.
    113     boolean mAnimating;
    114     boolean mLocalAnimating;
    115     Animation mAnimation;
    116     boolean mAnimationIsEntrance;
    117     boolean mHasTransformation;
    118     boolean mHasLocalTransformation;
    119     final Transformation mTransformation = new Transformation();
    120     boolean mWasAnimating;      // Were we animating going into the most recent animation step?
    121     int mAnimLayer;
    122     int mLastLayer;
    123     long mAnimationStartTime;
    124     long mLastAnimationTime;
    125     int mStackClip = STACK_CLIP_BEFORE_ANIM;
    126 
    127     /**
    128      * Set when we have changed the size of the surface, to know that
    129      * we must tell them application to resize (and thus redraw itself).
    130      */
    131     boolean mSurfaceResized;
    132     /**
    133      * Whether we should inform the client on next relayoutWindow that
    134      * the surface has been resized since last time.
    135      */
    136     boolean mReportSurfaceResized;
    137     WindowSurfaceController mSurfaceController;
    138     private WindowSurfaceController mPendingDestroySurface;
    139 
    140     /**
    141      * Set if the client has asked that the destroy of its surface be delayed
    142      * until it explicitly says it is okay.
    143      */
    144     boolean mSurfaceDestroyDeferred;
    145 
    146     private boolean mDestroyPreservedSurfaceUponRedraw;
    147     float mShownAlpha = 0;
    148     float mAlpha = 0;
    149     float mLastAlpha = 0;
    150 
    151     boolean mHasClipRect;
    152     Rect mClipRect = new Rect();
    153     Rect mTmpClipRect = new Rect();
    154     Rect mTmpFinalClipRect = new Rect();
    155     Rect mLastClipRect = new Rect();
    156     Rect mLastFinalClipRect = new Rect();
    157     Rect mTmpStackBounds = new Rect();
    158     private Rect mTmpAnimatingBounds = new Rect();
    159     private Rect mTmpSourceBounds = new Rect();
    160 
    161     /**
    162      * This is rectangle of the window's surface that is not covered by
    163      * system decorations.
    164      */
    165     private final Rect mSystemDecorRect = new Rect();
    166     private final Rect mLastSystemDecorRect = new Rect();
    167 
    168     // Used to save animation distances between the time they are calculated and when they are used.
    169     private int mAnimDx;
    170     private int mAnimDy;
    171 
    172     /** Is the next animation to be started a window move animation? */
    173     private boolean mAnimateMove = false;
    174 
    175     float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
    176     private float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
    177 
    178     boolean mHaveMatrix;
    179 
    180     // Set to true if, when the window gets displayed, it should perform
    181     // an enter animation.
    182     boolean mEnterAnimationPending;
    183 
    184     /** Used to indicate that this window is undergoing an enter animation. Used for system
    185      * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
    186      * window is first added or shown, cleared when the callback has been made. */
    187     boolean mEnteringAnimation;
    188 
    189     private boolean mAnimationStartDelayed;
    190 
    191     /** The pixel format of the underlying SurfaceControl */
    192     int mSurfaceFormat;
    193 
    194     /** This is set when there is no Surface */
    195     static final int NO_SURFACE = 0;
    196     /** This is set after the Surface has been created but before the window has been drawn. During
    197      * this time the surface is hidden. */
    198     static final int DRAW_PENDING = 1;
    199     /** This is set after the window has finished drawing for the first time but before its surface
    200      * is shown.  The surface will be displayed when the next layout is run. */
    201     static final int COMMIT_DRAW_PENDING = 2;
    202     /** This is set during the time after the window's drawing has been committed, and before its
    203      * surface is actually shown.  It is used to delay showing the surface until all windows in a
    204      * token are ready to be shown. */
    205     static final int READY_TO_SHOW = 3;
    206     /** Set when the window has been shown in the screen the first time. */
    207     static final int HAS_DRAWN = 4;
    208 
    209     String drawStateToString() {
    210         switch (mDrawState) {
    211             case NO_SURFACE: return "NO_SURFACE";
    212             case DRAW_PENDING: return "DRAW_PENDING";
    213             case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
    214             case READY_TO_SHOW: return "READY_TO_SHOW";
    215             case HAS_DRAWN: return "HAS_DRAWN";
    216             default: return Integer.toString(mDrawState);
    217         }
    218     }
    219     int mDrawState;
    220 
    221     /** Was this window last hidden? */
    222     boolean mLastHidden;
    223 
    224     int mAttrType;
    225 
    226     static final long PENDING_TRANSACTION_FINISH_WAIT_TIME = 100;
    227 
    228     boolean mForceScaleUntilResize;
    229 
    230     // WindowState.mHScale and WindowState.mVScale contain the
    231     // scale according to client specified layout parameters (e.g.
    232     // one layout size, with another surface size, creates such scaling).
    233     // Here we track an additional scaling factor used to follow stack
    234     // scaling (as in the case of the Pinned stack animation).
    235     float mExtraHScale = (float) 1.0;
    236     float mExtraVScale = (float) 1.0;
    237 
    238     private final Rect mTmpSize = new Rect();
    239 
    240     WindowStateAnimator(final WindowState win) {
    241         final WindowManagerService service = win.mService;
    242 
    243         mService = service;
    244         mAnimator = service.mAnimator;
    245         mPolicy = service.mPolicy;
    246         mContext = service.mContext;
    247         final DisplayContent displayContent = win.getDisplayContent();
    248         if (displayContent != null) {
    249             final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    250             mAnimDx = displayInfo.appWidth;
    251             mAnimDy = displayInfo.appHeight;
    252         } else {
    253             Slog.w(TAG, "WindowStateAnimator ctor: Display has been removed");
    254             // This is checked on return and dealt with.
    255         }
    256 
    257         mWin = win;
    258         mParentWinAnimator = !win.isChildWindow() ? null : win.getParentWindow().mWinAnimator;
    259         mAppAnimator = win.mAppToken == null ? null : win.mAppToken.mAppAnimator;
    260         mSession = win.mSession;
    261         mAttrType = win.mAttrs.type;
    262         mIsWallpaper = win.mIsWallpaper;
    263         mWallpaperControllerLocked = mService.mRoot.mWallpaperController;
    264     }
    265 
    266     public void setAnimation(Animation anim, long startTime, int stackClip) {
    267         if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
    268         mAnimating = false;
    269         mLocalAnimating = false;
    270         mAnimation = anim;
    271         mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
    272         mAnimation.scaleCurrentDuration(mService.getWindowAnimationScaleLocked());
    273         // Start out animation gone if window is gone, or visible if window is visible.
    274         mTransformation.clear();
    275         mTransformation.setAlpha(mLastHidden ? 0 : 1);
    276         mHasLocalTransformation = true;
    277         mAnimationStartTime = startTime;
    278         mStackClip = stackClip;
    279     }
    280 
    281     public void setAnimation(Animation anim, int stackClip) {
    282         setAnimation(anim, -1, stackClip);
    283     }
    284 
    285     public void setAnimation(Animation anim) {
    286         setAnimation(anim, -1, STACK_CLIP_AFTER_ANIM);
    287     }
    288 
    289     public void clearAnimation() {
    290         if (mAnimation != null) {
    291             mAnimating = true;
    292             mLocalAnimating = false;
    293             mAnimation.cancel();
    294             mAnimation = null;
    295             mStackClip = STACK_CLIP_BEFORE_ANIM;
    296         }
    297     }
    298 
    299     /**
    300      * Is the window or its container currently set to animate or currently animating?
    301      */
    302     boolean isAnimationSet() {
    303         return mAnimation != null
    304                 || (mParentWinAnimator != null && mParentWinAnimator.mAnimation != null)
    305                 || (mAppAnimator != null && mAppAnimator.isAnimating());
    306     }
    307 
    308     /**
    309      * @return whether an animation is about to start, i.e. the animation is set already but we
    310      *         haven't processed the first frame yet.
    311      */
    312     boolean isAnimationStarting() {
    313         return isAnimationSet() && !mAnimating;
    314     }
    315 
    316     /** Is the window animating the DummyAnimation? */
    317     boolean isDummyAnimation() {
    318         return mAppAnimator != null
    319                 && mAppAnimator.animation == sDummyAnimation;
    320     }
    321 
    322     /**
    323      * Is this window currently set to animate or currently animating?
    324      */
    325     boolean isWindowAnimationSet() {
    326         return mAnimation != null;
    327     }
    328 
    329     /**
    330      * Is this window currently waiting to run an opening animation?
    331      */
    332     boolean isWaitingForOpening() {
    333         return mService.mAppTransition.isTransitionSet() && isDummyAnimation()
    334                 && mService.mOpeningApps.contains(mWin.mAppToken);
    335     }
    336 
    337     void cancelExitAnimationForNextAnimationLocked() {
    338         if (DEBUG_ANIM) Slog.d(TAG,
    339                 "cancelExitAnimationForNextAnimationLocked: " + mWin);
    340 
    341         if (mAnimation != null) {
    342             mAnimation.cancel();
    343             mAnimation = null;
    344             mLocalAnimating = false;
    345             mWin.destroyOrSaveSurfaceUnchecked();
    346         }
    347     }
    348 
    349     private boolean stepAnimation(long currentTime) {
    350         if ((mAnimation == null) || !mLocalAnimating) {
    351             return false;
    352         }
    353         currentTime = getAnimationFrameTime(mAnimation, currentTime);
    354         mTransformation.clear();
    355         final boolean more = mAnimation.getTransformation(currentTime, mTransformation);
    356         if (mAnimationStartDelayed && mAnimationIsEntrance) {
    357             mTransformation.setAlpha(0f);
    358         }
    359         if (false && DEBUG_ANIM) Slog.v(TAG, "Stepped animation in " + this + ": more=" + more
    360                 + ", xform=" + mTransformation);
    361         return more;
    362     }
    363 
    364     // This must be called while inside a transaction.  Returns true if
    365     // there is more animation to run.
    366     boolean stepAnimationLocked(long currentTime) {
    367         // Save the animation state as it was before this step so WindowManagerService can tell if
    368         // we just started or just stopped animating by comparing mWasAnimating with isAnimationSet().
    369         mWasAnimating = mAnimating;
    370         final DisplayContent displayContent = mWin.getDisplayContent();
    371         if (displayContent != null && mService.okToDisplay()) {
    372             // We will run animations as long as the display isn't frozen.
    373 
    374             if (mWin.isDrawnLw() && mAnimation != null) {
    375                 mHasTransformation = true;
    376                 mHasLocalTransformation = true;
    377                 if (!mLocalAnimating) {
    378                     if (DEBUG_ANIM) Slog.v(
    379                         TAG, "Starting animation in " + this +
    380                         " @ " + currentTime + ": ww=" + mWin.mFrame.width() +
    381                         " wh=" + mWin.mFrame.height() +
    382                         " dx=" + mAnimDx + " dy=" + mAnimDy +
    383                         " scale=" + mService.getWindowAnimationScaleLocked());
    384                     final DisplayInfo displayInfo = displayContent.getDisplayInfo();
    385                     if (mAnimateMove) {
    386                         mAnimateMove = false;
    387                         mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
    388                                 mAnimDx, mAnimDy);
    389                     } else {
    390                         mAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(),
    391                                 displayInfo.appWidth, displayInfo.appHeight);
    392                     }
    393                     mAnimDx = displayInfo.appWidth;
    394                     mAnimDy = displayInfo.appHeight;
    395                     mAnimation.setStartTime(mAnimationStartTime != -1
    396                             ? mAnimationStartTime
    397                             : currentTime);
    398                     mLocalAnimating = true;
    399                     mAnimating = true;
    400                 }
    401                 if ((mAnimation != null) && mLocalAnimating) {
    402                     mLastAnimationTime = currentTime;
    403                     if (stepAnimation(currentTime)) {
    404                         return true;
    405                     }
    406                 }
    407                 if (DEBUG_ANIM) Slog.v(
    408                     TAG, "Finished animation in " + this +
    409                     " @ " + currentTime);
    410                 //WindowManagerService.this.dump();
    411             }
    412             mHasLocalTransformation = false;
    413             if ((!mLocalAnimating || mAnimationIsEntrance) && mAppAnimator != null
    414                     && mAppAnimator.animation != null) {
    415                 // When our app token is animating, we kind-of pretend like
    416                 // we are as well.  Note the mLocalAnimating mAnimationIsEntrance
    417                 // part of this check means that we will only do this if
    418                 // our window is not currently exiting, or it is not
    419                 // locally animating itself.  The idea being that one that
    420                 // is exiting and doing a local animation should be removed
    421                 // once that animation is done.
    422                 mAnimating = true;
    423                 mHasTransformation = true;
    424                 mTransformation.clear();
    425                 return false;
    426             } else if (mHasTransformation) {
    427                 // Little trick to get through the path below to act like
    428                 // we have finished an animation.
    429                 mAnimating = true;
    430             } else if (isAnimationSet()) {
    431                 mAnimating = true;
    432             }
    433         } else if (mAnimation != null) {
    434             // If the display is frozen, and there is a pending animation,
    435             // clear it and make sure we run the cleanup code.
    436             mAnimating = true;
    437         }
    438 
    439         if (!mAnimating && !mLocalAnimating) {
    440             return false;
    441         }
    442 
    443         // Done animating, clean up.
    444         if (DEBUG_ANIM) Slog.v(
    445             TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
    446             + ", reportedVisible="
    447             + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
    448 
    449         mAnimating = false;
    450         mLocalAnimating = false;
    451         if (mAnimation != null) {
    452             mAnimation.cancel();
    453             mAnimation = null;
    454         }
    455         if (mAnimator.mWindowDetachedWallpaper == mWin) {
    456             mAnimator.mWindowDetachedWallpaper = null;
    457         }
    458         mAnimLayer = mWin.getSpecialWindowAnimLayerAdjustment();
    459         if (DEBUG_LAYERS) Slog.v(TAG, "Stepping win " + this + " anim layer: " + mAnimLayer);
    460         mHasTransformation = false;
    461         mHasLocalTransformation = false;
    462         mStackClip = STACK_CLIP_BEFORE_ANIM;
    463         mWin.checkPolicyVisibilityChange();
    464         mTransformation.clear();
    465         if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
    466             // Upon completion of a not-visible to visible status bar animation a relayout is
    467             // required.
    468             if (displayContent != null) {
    469                 displayContent.setLayoutNeeded();
    470             }
    471         }
    472 
    473         mWin.onExitAnimationDone();
    474         final int displayId = mWin.getDisplayId();
    475         mAnimator.setPendingLayoutChanges(displayId, WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
    476         if (DEBUG_LAYOUT_REPEATS)
    477             mService.mWindowPlacerLocked.debugLayoutRepeats(
    478                     "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));
    479 
    480         if (mWin.mAppToken != null) {
    481             mWin.mAppToken.updateReportedVisibilityLocked();
    482         }
    483 
    484         return false;
    485     }
    486 
    487     void hide(String reason) {
    488         if (!mLastHidden) {
    489             //dump();
    490             mLastHidden = true;
    491             if (mSurfaceController != null) {
    492                 mSurfaceController.hideInTransaction(reason);
    493             }
    494         }
    495     }
    496 
    497     boolean finishDrawingLocked() {
    498         final boolean startingWindow =
    499                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
    500         if (DEBUG_STARTING_WINDOW && startingWindow) {
    501             Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
    502                     + drawStateToString());
    503         }
    504 
    505         boolean layoutNeeded = mWin.clearAnimatingWithSavedSurface();
    506 
    507         if (mDrawState == DRAW_PENDING) {
    508             if (DEBUG_SURFACE_TRACE || DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
    509                 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
    510                         + mSurfaceController);
    511             if (DEBUG_STARTING_WINDOW && startingWindow) {
    512                 Slog.v(TAG, "Draw state now committed in " + mWin);
    513             }
    514             mDrawState = COMMIT_DRAW_PENDING;
    515             layoutNeeded = true;
    516         }
    517 
    518         return layoutNeeded;
    519     }
    520 
    521     // This must be called while inside a transaction.
    522     boolean commitFinishDrawingLocked() {
    523         if (DEBUG_STARTING_WINDOW_VERBOSE &&
    524                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
    525             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
    526                     + drawStateToString());
    527         }
    528         if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
    529             return false;
    530         }
    531         if (DEBUG_SURFACE_TRACE || DEBUG_ANIM) {
    532             Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController);
    533         }
    534         mDrawState = READY_TO_SHOW;
    535         boolean result = false;
    536         final AppWindowToken atoken = mWin.mAppToken;
    537         if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
    538             result = mWin.performShowLocked();
    539         }
    540         return result;
    541     }
    542 
    543     void preserveSurfaceLocked() {
    544         if (mDestroyPreservedSurfaceUponRedraw) {
    545             // This could happen when switching the surface mode very fast. For example,
    546             // we preserved a surface when dragResizing changed to true. Then before the
    547             // preserved surface is removed, dragResizing changed to false again.
    548             // In this case, we need to leave the preserved surface alone, and destroy
    549             // the actual surface, so that the createSurface call could create a surface
    550             // of the proper size. The preserved surface will still be removed when client
    551             // finishes drawing to the new surface.
    552             mSurfaceDestroyDeferred = false;
    553             destroySurfaceLocked();
    554             mSurfaceDestroyDeferred = true;
    555             return;
    556         }
    557         if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "SET FREEZE LAYER", false);
    558         if (mSurfaceController != null) {
    559             mSurfaceController.setLayer(mAnimLayer + 1);
    560         }
    561         mDestroyPreservedSurfaceUponRedraw = true;
    562         mSurfaceDestroyDeferred = true;
    563         destroySurfaceLocked();
    564     }
    565 
    566     void destroyPreservedSurfaceLocked() {
    567         if (!mDestroyPreservedSurfaceUponRedraw) {
    568             return;
    569         }
    570         if (mSurfaceController != null) {
    571             if (mPendingDestroySurface != null) {
    572                 // If we are preserving a surface but we aren't relaunching that means
    573                 // we are just doing an in-place switch. In that case any SurfaceFlinger side
    574                 // child layers need to be reparented to the new surface to make this
    575                 // transparent to the app.
    576                 if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
    577                     SurfaceControl.openTransaction();
    578                     mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
    579                     SurfaceControl.closeTransaction();
    580                 }
    581             }
    582         }
    583 
    584         destroyDeferredSurfaceLocked();
    585         mDestroyPreservedSurfaceUponRedraw = false;
    586     }
    587 
    588     void markPreservedSurfaceForDestroy() {
    589         if (mDestroyPreservedSurfaceUponRedraw
    590                 && !mService.mDestroyPreservedSurface.contains(mWin)) {
    591             mService.mDestroyPreservedSurface.add(mWin);
    592         }
    593     }
    594 
    595     private int getLayerStack() {
    596         return mWin.getDisplayContent().getDisplay().getLayerStack();
    597     }
    598 
    599     void updateLayerStackInTransaction() {
    600         if (mSurfaceController != null) {
    601             mSurfaceController.setLayerStackInTransaction(
    602                     getLayerStack());
    603         }
    604     }
    605 
    606     void resetDrawState() {
    607         mDrawState = DRAW_PENDING;
    608 
    609         if (mWin.mAppToken == null) {
    610             return;
    611         }
    612 
    613         if (mWin.mAppToken.mAppAnimator.animation == null) {
    614             mWin.mAppToken.clearAllDrawn();
    615         } else {
    616             // Currently animating, persist current state of allDrawn until animation
    617             // is complete.
    618             mWin.mAppToken.deferClearAllDrawn = true;
    619         }
    620     }
    621 
    622     WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
    623         final WindowState w = mWin;
    624         if (w.restoreSavedSurface()) {
    625             if (DEBUG_ANIM) Slog.i(TAG,
    626                     "createSurface: " + this + ": called when we had a saved surface");
    627             return mSurfaceController;
    628         }
    629 
    630         if (mSurfaceController != null) {
    631             return mSurfaceController;
    632         }
    633 
    634         w.setHasSurface(false);
    635 
    636         if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
    637                 "createSurface " + this + ": mDrawState=DRAW_PENDING");
    638 
    639         resetDrawState();
    640 
    641         mService.makeWindowFreezingScreenIfNeededLocked(w);
    642 
    643         int flags = SurfaceControl.HIDDEN;
    644         final WindowManager.LayoutParams attrs = w.mAttrs;
    645 
    646         if (mService.isSecureLocked(w)) {
    647             flags |= SurfaceControl.SECURE;
    648         }
    649 
    650         mTmpSize.set(w.mFrame.left + w.mXOffset, w.mFrame.top + w.mYOffset, 0, 0);
    651         calculateSurfaceBounds(w, attrs);
    652         final int width = mTmpSize.width();
    653         final int height = mTmpSize.height();
    654 
    655         if (DEBUG_VISIBILITY) {
    656             Slog.v(TAG, "Creating surface in session "
    657                     + mSession.mSurfaceSession + " window " + this
    658                     + " w=" + width + " h=" + height
    659                     + " x=" + mTmpSize.left + " y=" + mTmpSize.top
    660                     + " format=" + attrs.format + " flags=" + flags);
    661         }
    662 
    663         // We may abort, so initialize to defaults.
    664         mLastSystemDecorRect.set(0, 0, 0, 0);
    665         mHasClipRect = false;
    666         mClipRect.set(0, 0, 0, 0);
    667         mLastClipRect.set(0, 0, 0, 0);
    668 
    669         // Set up surface control with initial size.
    670         try {
    671 
    672             final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
    673             final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
    674             if (!PixelFormat.formatHasAlpha(attrs.format)
    675                     // Don't make surface with surfaceInsets opaque as they display a
    676                     // translucent shadow.
    677                     && attrs.surfaceInsets.left == 0
    678                     && attrs.surfaceInsets.top == 0
    679                     && attrs.surfaceInsets.right == 0
    680                     && attrs.surfaceInsets.bottom == 0
    681                     // Don't make surface opaque when resizing to reduce the amount of
    682                     // artifacts shown in areas the app isn't drawing content to.
    683                     && !w.isDragResizing()) {
    684                 flags |= SurfaceControl.OPAQUE;
    685             }
    686 
    687             mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
    688                     attrs.getTitle().toString(),
    689                     width, height, format, flags, this, windowType, ownerUid);
    690             mSurfaceFormat = format;
    691 
    692             w.setHasSurface(true);
    693 
    694             if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    695                 Slog.i(TAG, "  CREATE SURFACE "
    696                         + mSurfaceController + " IN SESSION "
    697                         + mSession.mSurfaceSession
    698                         + ": pid=" + mSession.mPid + " format="
    699                         + attrs.format + " flags=0x"
    700                         + Integer.toHexString(flags)
    701                         + " / " + this);
    702             }
    703         } catch (OutOfResourcesException e) {
    704             Slog.w(TAG, "OutOfResourcesException creating surface");
    705             mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
    706             mDrawState = NO_SURFACE;
    707             return null;
    708         } catch (Exception e) {
    709             Slog.e(TAG, "Exception creating surface", e);
    710             mDrawState = NO_SURFACE;
    711             return null;
    712         }
    713 
    714         if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
    715                 + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
    716                 + ", animLayer=" + mAnimLayer);
    717 
    718         if (SHOW_LIGHT_TRANSACTIONS) {
    719             Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
    720             WindowManagerService.logSurface(w, "CREATE pos=("
    721                     + w.mFrame.left + "," + w.mFrame.top + ") ("
    722                     + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
    723         }
    724 
    725         // Start a new transaction and apply position & offset.
    726 
    727         mService.openSurfaceTransaction();
    728         try {
    729             mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top, false);
    730             mSurfaceController.setLayerStackInTransaction(getLayerStack());
    731             mSurfaceController.setLayer(mAnimLayer);
    732         } finally {
    733             mService.closeSurfaceTransaction();
    734         }
    735 
    736         mLastHidden = true;
    737 
    738         if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
    739         return mSurfaceController;
    740     }
    741 
    742     private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) {
    743         if ((attrs.flags & FLAG_SCALED) != 0) {
    744             // For a scaled surface, we always want the requested size.
    745             mTmpSize.right = mTmpSize.left + w.mRequestedWidth;
    746             mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight;
    747         } else {
    748             // When we're doing a drag-resizing, request a surface that's fullscreen size,
    749             // so that we don't need to reallocate during the process. This also prevents
    750             // buffer drops due to size mismatch.
    751             if (w.isDragResizing()) {
    752                 if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) {
    753                     mTmpSize.left = 0;
    754                     mTmpSize.top = 0;
    755                 }
    756                 final DisplayInfo displayInfo = w.getDisplayInfo();
    757                 mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth;
    758                 mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight;
    759             } else {
    760                 mTmpSize.right = mTmpSize.left + w.mCompatFrame.width();
    761                 mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height();
    762             }
    763         }
    764 
    765         // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
    766         // This doesn't necessarily mean that there is an error in the system. The sizes might be
    767         // incorrect, because it is before the first layout or draw.
    768         if (mTmpSize.width() < 1) {
    769             mTmpSize.right = mTmpSize.left + 1;
    770         }
    771         if (mTmpSize.height() < 1) {
    772             mTmpSize.bottom = mTmpSize.top + 1;
    773         }
    774 
    775         // Adjust for surface insets.
    776         mTmpSize.left -= attrs.surfaceInsets.left;
    777         mTmpSize.top -= attrs.surfaceInsets.top;
    778         mTmpSize.right += attrs.surfaceInsets.right;
    779         mTmpSize.bottom += attrs.surfaceInsets.bottom;
    780     }
    781 
    782     boolean hasSurface() {
    783         return !mWin.hasSavedSurface()
    784                 && mSurfaceController != null && mSurfaceController.hasSurface();
    785     }
    786 
    787     void destroySurfaceLocked() {
    788         final AppWindowToken wtoken = mWin.mAppToken;
    789         if (wtoken != null) {
    790             if (mWin == wtoken.startingWindow) {
    791                 wtoken.startingDisplayed = false;
    792             }
    793         }
    794 
    795         mWin.clearHasSavedSurface();
    796 
    797         if (mSurfaceController == null) {
    798             return;
    799         }
    800 
    801         // When destroying a surface we want to make sure child windows are hidden. If we are
    802         // preserving the surface until redraw though we intend to swap it out with another surface
    803         // for resizing. In this case the window always remains visible to the user and the child
    804         // windows should likewise remain visible.
    805         if (!mDestroyPreservedSurfaceUponRedraw) {
    806             mWin.mHidden = true;
    807         }
    808 
    809         try {
    810             if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface "
    811                     + mSurfaceController + ", session " + mSession);
    812             if (mSurfaceDestroyDeferred) {
    813                 if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) {
    814                     if (mPendingDestroySurface != null) {
    815                         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    816                             WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
    817                         }
    818                         mPendingDestroySurface.destroyInTransaction();
    819                     }
    820                     mPendingDestroySurface = mSurfaceController;
    821                 }
    822             } else {
    823                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    824                     WindowManagerService.logSurface(mWin, "DESTROY", true);
    825                 }
    826                 destroySurface();
    827             }
    828             // Don't hide wallpaper if we're deferring the surface destroy
    829             // because of a surface change.
    830             if (!mDestroyPreservedSurfaceUponRedraw) {
    831                 mWallpaperControllerLocked.hideWallpapers(mWin);
    832             }
    833         } catch (RuntimeException e) {
    834             Slog.w(TAG, "Exception thrown when destroying Window " + this
    835                 + " surface " + mSurfaceController + " session " + mSession + ": " + e.toString());
    836         }
    837 
    838         // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it
    839         // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary
    840         // so it can be recreated successfully in mPendingDestroySurface case.
    841         mWin.setHasSurface(false);
    842         if (mSurfaceController != null) {
    843             mSurfaceController.setShown(false);
    844         }
    845         mSurfaceController = null;
    846         mDrawState = NO_SURFACE;
    847     }
    848 
    849     void destroyDeferredSurfaceLocked() {
    850         try {
    851             if (mPendingDestroySurface != null) {
    852                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
    853                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
    854                 }
    855                 mPendingDestroySurface.destroyInTransaction();
    856                 // Don't hide wallpaper if we're destroying a deferred surface
    857                 // after a surface mode change.
    858                 if (!mDestroyPreservedSurfaceUponRedraw) {
    859                     mWallpaperControllerLocked.hideWallpapers(mWin);
    860                 }
    861             }
    862         } catch (RuntimeException e) {
    863             Slog.w(TAG, "Exception thrown when destroying Window "
    864                     + this + " surface " + mPendingDestroySurface
    865                     + " session " + mSession + ": " + e.toString());
    866         }
    867         mSurfaceDestroyDeferred = false;
    868         mPendingDestroySurface = null;
    869     }
    870 
    871     void applyMagnificationSpec(MagnificationSpec spec, Matrix transform) {
    872         final int surfaceInsetLeft = mWin.mAttrs.surfaceInsets.left;
    873         final int surfaceInsetTop = mWin.mAttrs.surfaceInsets.top;
    874 
    875         if (spec != null && !spec.isNop()) {
    876             float scale = spec.scale;
    877             transform.postScale(scale, scale);
    878             transform.postTranslate(spec.offsetX, spec.offsetY);
    879 
    880             // As we are scaling the whole surface, to keep the content
    881             // in the same position we will also have to scale the surfaceInsets.
    882             transform.postTranslate(-(surfaceInsetLeft*scale - surfaceInsetLeft),
    883                     -(surfaceInsetTop*scale - surfaceInsetTop));
    884         }
    885     }
    886 
    887     void computeShownFrameLocked() {
    888         final boolean selfTransformation = mHasLocalTransformation;
    889         Transformation attachedTransformation =
    890                 (mParentWinAnimator != null && mParentWinAnimator.mHasLocalTransformation)
    891                 ? mParentWinAnimator.mTransformation : null;
    892         Transformation appTransformation = (mAppAnimator != null && mAppAnimator.hasTransformation)
    893                 ? mAppAnimator.transformation : null;
    894 
    895         // Wallpapers are animated based on the "real" window they
    896         // are currently targeting.
    897         final WindowState wallpaperTarget = mWallpaperControllerLocked.getWallpaperTarget();
    898         if (mIsWallpaper && wallpaperTarget != null && mService.mAnimateWallpaperWithTarget) {
    899             final WindowStateAnimator wallpaperAnimator = wallpaperTarget.mWinAnimator;
    900             if (wallpaperAnimator.mHasLocalTransformation &&
    901                     wallpaperAnimator.mAnimation != null &&
    902                     !wallpaperAnimator.mAnimation.getDetachWallpaper()) {
    903                 attachedTransformation = wallpaperAnimator.mTransformation;
    904                 if (DEBUG_WALLPAPER && attachedTransformation != null) {
    905                     Slog.v(TAG, "WP target attached xform: " + attachedTransformation);
    906                 }
    907             }
    908             final AppWindowAnimator wpAppAnimator = wallpaperTarget.mAppToken == null ?
    909                     null : wallpaperTarget.mAppToken.mAppAnimator;
    910                 if (wpAppAnimator != null && wpAppAnimator.hasTransformation
    911                     && wpAppAnimator.animation != null
    912                     && !wpAppAnimator.animation.getDetachWallpaper()) {
    913                 appTransformation = wpAppAnimator.transformation;
    914                 if (DEBUG_WALLPAPER && appTransformation != null) {
    915                     Slog.v(TAG, "WP target app xform: " + appTransformation);
    916                 }
    917             }
    918         }
    919 
    920         final int displayId = mWin.getDisplayId();
    921         final ScreenRotationAnimation screenRotationAnimation =
    922                 mAnimator.getScreenRotationAnimationLocked(displayId);
    923         final boolean screenAnimation =
    924                 screenRotationAnimation != null && screenRotationAnimation.isAnimating();
    925 
    926         mHasClipRect = false;
    927         if (selfTransformation || attachedTransformation != null
    928                 || appTransformation != null || screenAnimation) {
    929             // cache often used attributes locally
    930             final Rect frame = mWin.mFrame;
    931             final float tmpFloats[] = mService.mTmpFloats;
    932             final Matrix tmpMatrix = mWin.mTmpMatrix;
    933 
    934             // Compute the desired transformation.
    935             if (screenAnimation && screenRotationAnimation.isRotating()) {
    936                 // If we are doing a screen animation, the global rotation
    937                 // applied to windows can result in windows that are carefully
    938                 // aligned with each other to slightly separate, allowing you
    939                 // to see what is behind them.  An unsightly mess.  This...
    940                 // thing...  magically makes it call good: scale each window
    941                 // slightly (two pixels larger in each dimension, from the
    942                 // window's center).
    943                 final float w = frame.width();
    944                 final float h = frame.height();
    945                 if (w>=1 && h>=1) {
    946                     tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
    947                 } else {
    948                     tmpMatrix.reset();
    949                 }
    950             } else {
    951                 tmpMatrix.reset();
    952             }
    953             tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
    954             if (selfTransformation) {
    955                 tmpMatrix.postConcat(mTransformation.getMatrix());
    956             }
    957             if (attachedTransformation != null) {
    958                 tmpMatrix.postConcat(attachedTransformation.getMatrix());
    959             }
    960             if (appTransformation != null) {
    961                 tmpMatrix.postConcat(appTransformation.getMatrix());
    962             }
    963 
    964             // The translation that applies the position of the window needs to be applied at the
    965             // end in case that other translations include scaling. Otherwise the scaling will
    966             // affect this translation. But it needs to be set before the screen rotation animation
    967             // so the pivot point is at the center of the screen for all windows.
    968             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
    969             if (screenAnimation) {
    970                 tmpMatrix.postConcat(screenRotationAnimation.getEnterTransformation().getMatrix());
    971             }
    972 
    973             MagnificationSpec spec = getMagnificationSpec();
    974             if (spec != null) {
    975                 applyMagnificationSpec(spec, tmpMatrix);
    976             }
    977 
    978             // "convert" it into SurfaceFlinger's format
    979             // (a 2x2 matrix + an offset)
    980             // Here we must not transform the position of the surface
    981             // since it is already included in the transformation.
    982             //Slog.i(TAG_WM, "Transform: " + matrix);
    983 
    984             mHaveMatrix = true;
    985             tmpMatrix.getValues(tmpFloats);
    986             mDsDx = tmpFloats[Matrix.MSCALE_X];
    987             mDtDx = tmpFloats[Matrix.MSKEW_Y];
    988             mDtDy = tmpFloats[Matrix.MSKEW_X];
    989             mDsDy = tmpFloats[Matrix.MSCALE_Y];
    990             float x = tmpFloats[Matrix.MTRANS_X];
    991             float y = tmpFloats[Matrix.MTRANS_Y];
    992             mWin.mShownPosition.set(Math.round(x), Math.round(y));
    993 
    994             // Now set the alpha...  but because our current hardware
    995             // can't do alpha transformation on a non-opaque surface,
    996             // turn it off if we are running an animation that is also
    997             // transforming since it is more important to have that
    998             // animation be smooth.
    999             mShownAlpha = mAlpha;
   1000             if (!mService.mLimitedAlphaCompositing
   1001                     || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
   1002                     || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)
   1003                             && x == frame.left && y == frame.top))) {
   1004                 //Slog.i(TAG_WM, "Applying alpha transform");
   1005                 if (selfTransformation) {
   1006                     mShownAlpha *= mTransformation.getAlpha();
   1007                 }
   1008                 if (attachedTransformation != null) {
   1009                     mShownAlpha *= attachedTransformation.getAlpha();
   1010                 }
   1011                 if (appTransformation != null) {
   1012                     mShownAlpha *= appTransformation.getAlpha();
   1013                     if (appTransformation.hasClipRect()) {
   1014                         mClipRect.set(appTransformation.getClipRect());
   1015                         mHasClipRect = true;
   1016                         // The app transformation clip will be in the coordinate space of the main
   1017                         // activity window, which the animation correctly assumes will be placed at
   1018                         // (0,0)+(insets) relative to the containing frame. This isn't necessarily
   1019                         // true for child windows though which can have an arbitrary frame position
   1020                         // relative to their containing frame. We need to offset the difference
   1021                         // between the containing frame as used to calculate the crop and our
   1022                         // bounds to compensate for this.
   1023                         if (mWin.layoutInParentFrame()) {
   1024                             mClipRect.offset( (mWin.mContainingFrame.left - mWin.mFrame.left),
   1025                                     mWin.mContainingFrame.top - mWin.mFrame.top );
   1026                         }
   1027                     }
   1028                 }
   1029                 if (screenAnimation) {
   1030                     mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
   1031                 }
   1032             } else {
   1033                 //Slog.i(TAG_WM, "Not applying alpha transform");
   1034             }
   1035 
   1036             if ((DEBUG_SURFACE_TRACE || WindowManagerService.localLOGV)
   1037                     && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
   1038                     TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
   1039                     + " self=" + (selfTransformation ? mTransformation.getAlpha() : "null")
   1040                     + " attached=" + (attachedTransformation == null ?
   1041                             "null" : attachedTransformation.getAlpha())
   1042                     + " app=" + (appTransformation == null ? "null" : appTransformation.getAlpha())
   1043                     + " screen=" + (screenAnimation ?
   1044                             screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
   1045             return;
   1046         } else if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
   1047             return;
   1048         } else if (mWin.isDragResizeChanged()) {
   1049             // This window is awaiting a relayout because user just started (or ended)
   1050             // drag-resizing. The shown frame (which affects surface size and pos)
   1051             // should not be updated until we get next finished draw with the new surface.
   1052             // Otherwise one or two frames rendered with old settings would be displayed
   1053             // with new geometry.
   1054             return;
   1055         }
   1056 
   1057         if (WindowManagerService.localLOGV) Slog.v(
   1058                 TAG, "computeShownFrameLocked: " + this +
   1059                 " not attached, mAlpha=" + mAlpha);
   1060 
   1061         MagnificationSpec spec = getMagnificationSpec();
   1062         if (spec != null) {
   1063             final Rect frame = mWin.mFrame;
   1064             final float tmpFloats[] = mService.mTmpFloats;
   1065             final Matrix tmpMatrix = mWin.mTmpMatrix;
   1066 
   1067             tmpMatrix.setScale(mWin.mGlobalScale, mWin.mGlobalScale);
   1068             tmpMatrix.postTranslate(frame.left + mWin.mXOffset, frame.top + mWin.mYOffset);
   1069 
   1070             applyMagnificationSpec(spec, tmpMatrix);
   1071 
   1072             tmpMatrix.getValues(tmpFloats);
   1073 
   1074             mHaveMatrix = true;
   1075             mDsDx = tmpFloats[Matrix.MSCALE_X];
   1076             mDtDx = tmpFloats[Matrix.MSKEW_Y];
   1077             mDtDy = tmpFloats[Matrix.MSKEW_X];
   1078             mDsDy = tmpFloats[Matrix.MSCALE_Y];
   1079             float x = tmpFloats[Matrix.MTRANS_X];
   1080             float y = tmpFloats[Matrix.MTRANS_Y];
   1081             mWin.mShownPosition.set(Math.round(x), Math.round(y));
   1082 
   1083             mShownAlpha = mAlpha;
   1084         } else {
   1085             mWin.mShownPosition.set(mWin.mFrame.left, mWin.mFrame.top);
   1086             if (mWin.mXOffset != 0 || mWin.mYOffset != 0) {
   1087                 mWin.mShownPosition.offset(mWin.mXOffset, mWin.mYOffset);
   1088             }
   1089             mShownAlpha = mAlpha;
   1090             mHaveMatrix = false;
   1091             mDsDx = mWin.mGlobalScale;
   1092             mDtDx = 0;
   1093             mDtDy = 0;
   1094             mDsDy = mWin.mGlobalScale;
   1095         }
   1096     }
   1097 
   1098     private MagnificationSpec getMagnificationSpec() {
   1099         //TODO (multidisplay): Magnification is supported only for the default display.
   1100         if (mService.mAccessibilityController != null && mWin.getDisplayId() == DEFAULT_DISPLAY) {
   1101             return mService.mAccessibilityController.getMagnificationSpecForWindowLocked(mWin);
   1102         }
   1103         return null;
   1104     }
   1105 
   1106     /**
   1107      * In some scenarios we use a screen space clip rect (so called, final clip rect)
   1108      * to crop to stack bounds. Generally because it's easier to deal with while
   1109      * animating.
   1110      *
   1111      * @return True in scenarios where we use the final clip rect for stack clipping.
   1112      */
   1113     private boolean useFinalClipRect() {
   1114         return (isAnimationSet() && resolveStackClip() == STACK_CLIP_AFTER_ANIM)
   1115                 || mDestroyPreservedSurfaceUponRedraw || mWin.inPinnedWorkspace();
   1116     }
   1117 
   1118     /**
   1119      * Calculate the screen-space crop rect and fill finalClipRect.
   1120      * @return true if finalClipRect has been filled, otherwise,
   1121      * no screen space crop should be applied.
   1122      */
   1123     private boolean calculateFinalCrop(Rect finalClipRect) {
   1124         final WindowState w = mWin;
   1125         final DisplayContent displayContent = w.getDisplayContent();
   1126         finalClipRect.setEmpty();
   1127 
   1128         if (displayContent == null) {
   1129             return false;
   1130         }
   1131 
   1132         if (!shouldCropToStackBounds() || !useFinalClipRect()) {
   1133             return false;
   1134         }
   1135 
   1136         // Task is non-null per shouldCropToStackBounds
   1137         final TaskStack stack = w.getTask().mStack;
   1138         stack.getDimBounds(finalClipRect);
   1139 
   1140         if (StackId.tasksAreFloating(stack.mStackId)) {
   1141             w.expandForSurfaceInsets(finalClipRect);
   1142         }
   1143 
   1144         // We may be applying a magnification spec to all windows,
   1145         // simulating a transformation in screen space, in which case
   1146         // we need to transform all other screen space values...including
   1147         // the final crop. This is kind of messed up and we should look
   1148         // in to actually transforming screen-space via a parent-layer.
   1149         // b/38322835
   1150         MagnificationSpec spec = getMagnificationSpec();
   1151         if (spec != null && !spec.isNop()) {
   1152             Matrix transform = mWin.mTmpMatrix;
   1153             RectF finalCrop = mService.mTmpRectF;
   1154             transform.reset();
   1155             transform.postScale(spec.scale, spec.scale);
   1156             transform.postTranslate(-spec.offsetX, -spec.offsetY);
   1157             transform.mapRect(finalCrop);
   1158             finalClipRect.top = (int)finalCrop.top;
   1159             finalClipRect.left = (int)finalCrop.left;
   1160             finalClipRect.right = (int)finalClipRect.right;
   1161             finalClipRect.bottom = (int)finalClipRect.bottom;
   1162         }
   1163 
   1164         return true;
   1165     }
   1166 
   1167     /**
   1168      * Calculate the window-space crop rect and fill clipRect.
   1169      * @return true if clipRect has been filled otherwise, no window space crop should be applied.
   1170      */
   1171     private boolean calculateCrop(Rect clipRect) {
   1172         final WindowState w = mWin;
   1173         final DisplayContent displayContent = w.getDisplayContent();
   1174         clipRect.setEmpty();
   1175 
   1176         if (displayContent == null) {
   1177             return false;
   1178         }
   1179 
   1180         if (w.inPinnedWorkspace()) {
   1181             return false;
   1182         }
   1183 
   1184         // If we're animating, the wallpaper should only
   1185         // be updated at the end of the animation.
   1186         if (w.mAttrs.type == TYPE_WALLPAPER) {
   1187             return false;
   1188         }
   1189 
   1190         if (DEBUG_WINDOW_CROP) Slog.d(TAG,
   1191                 "Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
   1192 
   1193         w.calculatePolicyCrop(mSystemDecorRect);
   1194 
   1195         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
   1196                 + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
   1197 
   1198         final boolean fullscreen = w.fillsDisplay();
   1199         final boolean isFreeformResizing =
   1200                 w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
   1201 
   1202         // We use the clip rect as provided by the tranformation for non-fullscreen windows to
   1203         // avoid premature clipping with the system decor rect.
   1204         clipRect.set((mHasClipRect && !fullscreen) ? mClipRect : mSystemDecorRect);
   1205         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
   1206                 + " mHasClipRect=" + mHasClipRect + " fullscreen=" + fullscreen);
   1207 
   1208         if (isFreeformResizing && !w.isChildWindow()) {
   1209             // For freeform resizing non child windows, we are using the big surface positioned
   1210             // at 0,0. Thus we must express the crop in that coordinate space.
   1211             clipRect.offset(w.mShownPosition.x, w.mShownPosition.y);
   1212         }
   1213 
   1214         w.expandForSurfaceInsets(clipRect);
   1215 
   1216         if (mHasClipRect && fullscreen) {
   1217             // We intersect the clip rect specified by the transformation with the expanded system
   1218             // decor rect to prevent artifacts from drawing during animation if the transformation
   1219             // clip rect extends outside the system decor rect.
   1220             clipRect.intersect(mClipRect);
   1221         }
   1222         // The clip rect was generated assuming (0,0) as the window origin,
   1223         // so we need to translate to match the actual surface coordinates.
   1224         clipRect.offset(w.mAttrs.surfaceInsets.left, w.mAttrs.surfaceInsets.top);
   1225 
   1226         if (!useFinalClipRect()) {
   1227             adjustCropToStackBounds(clipRect, isFreeformResizing);
   1228         }
   1229         if (DEBUG_WINDOW_CROP) Slog.d(TAG,
   1230                 "win=" + w + " Clip rect after stack adjustment=" + clipRect);
   1231 
   1232         w.transformClipRectFromScreenToSurfaceSpace(clipRect);
   1233 
   1234         return true;
   1235     }
   1236 
   1237     private void applyCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
   1238         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "applyCrop: win=" + mWin
   1239                 + " clipRect=" + clipRect + " finalClipRect=" + finalClipRect);
   1240         if (clipRect != null) {
   1241             if (!clipRect.equals(mLastClipRect)) {
   1242                 mLastClipRect.set(clipRect);
   1243                 mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
   1244             }
   1245         } else {
   1246             mSurfaceController.clearCropInTransaction(recoveringMemory);
   1247         }
   1248 
   1249         if (finalClipRect == null) {
   1250             finalClipRect = mService.mTmpRect;
   1251             finalClipRect.setEmpty();
   1252         }
   1253         if (!finalClipRect.equals(mLastFinalClipRect)) {
   1254             mLastFinalClipRect.set(finalClipRect);
   1255             mSurfaceController.setFinalCropInTransaction(finalClipRect);
   1256             if (mDestroyPreservedSurfaceUponRedraw && mPendingDestroySurface != null) {
   1257                 mPendingDestroySurface.setFinalCropInTransaction(finalClipRect);
   1258             }
   1259         }
   1260     }
   1261 
   1262     private int resolveStackClip() {
   1263         // App animation overrides window animation stack clip mode.
   1264         if (mAppAnimator != null && mAppAnimator.animation != null) {
   1265             return mAppAnimator.getStackClip();
   1266         } else {
   1267             return mStackClip;
   1268         }
   1269     }
   1270 
   1271     private boolean shouldCropToStackBounds() {
   1272         final WindowState w = mWin;
   1273         final DisplayContent displayContent = w.getDisplayContent();
   1274         if (displayContent != null && !displayContent.isDefaultDisplay) {
   1275             // There are some windows that live on other displays while their app and main window
   1276             // live on the default display (e.g. casting...). We don't want to crop this windows
   1277             // to the stack bounds which is only currently supported on the default display.
   1278             // TODO(multi-display): Need to support cropping to stack bounds on other displays
   1279             // when we have stacks on other displays.
   1280             return false;
   1281         }
   1282 
   1283         final Task task = w.getTask();
   1284         if (task == null || !task.cropWindowsToStackBounds()) {
   1285             return false;
   1286         }
   1287 
   1288         final int stackClip = resolveStackClip();
   1289 
   1290         // It's animating and we don't want to clip it to stack bounds during animation - abort.
   1291         if (isAnimationSet() && stackClip == STACK_CLIP_NONE) {
   1292             return false;
   1293         }
   1294         return true;
   1295     }
   1296 
   1297     private void adjustCropToStackBounds(Rect clipRect,
   1298             boolean isFreeformResizing) {
   1299         final WindowState w = mWin;
   1300 
   1301         if (!shouldCropToStackBounds()) {
   1302             return;
   1303         }
   1304 
   1305         final TaskStack stack = w.getTask().mStack;
   1306         stack.getDimBounds(mTmpStackBounds);
   1307         final Rect surfaceInsets = w.getAttrs().surfaceInsets;
   1308         // When we resize we use the big surface approach, which means we can't trust the
   1309         // window frame bounds anymore. Instead, the window will be placed at 0, 0, but to avoid
   1310         // hardcoding it, we use surface coordinates.
   1311         final int frameX = isFreeformResizing ? (int) mSurfaceController.getX() :
   1312                 w.mFrame.left + mWin.mXOffset - surfaceInsets.left;
   1313         final int frameY = isFreeformResizing ? (int) mSurfaceController.getY() :
   1314                 w.mFrame.top + mWin.mYOffset - surfaceInsets.top;
   1315 
   1316         // We need to do some acrobatics with surface position, because their clip region is
   1317         // relative to the inside of the surface, but the stack bounds aren't.
   1318         if (StackId.hasWindowShadow(stack.mStackId)
   1319                 && !StackId.isTaskResizeAllowed(stack.mStackId)) {
   1320                 // The windows in this stack display drop shadows and the fill the entire stack
   1321                 // area. Adjust the stack bounds we will use to cropping take into account the
   1322                 // offsets we use to display the drop shadow so it doesn't get cropped.
   1323                 mTmpStackBounds.inset(-surfaceInsets.left, -surfaceInsets.top,
   1324                         -surfaceInsets.right, -surfaceInsets.bottom);
   1325         }
   1326 
   1327         clipRect.left = Math.max(0,
   1328                 Math.max(mTmpStackBounds.left, frameX + clipRect.left) - frameX);
   1329         clipRect.top = Math.max(0,
   1330                 Math.max(mTmpStackBounds.top, frameY + clipRect.top) - frameY);
   1331         clipRect.right = Math.max(0,
   1332                 Math.min(mTmpStackBounds.right, frameX + clipRect.right) - frameX);
   1333         clipRect.bottom = Math.max(0,
   1334                 Math.min(mTmpStackBounds.bottom, frameY + clipRect.bottom) - frameY);
   1335     }
   1336 
   1337     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
   1338         if (mSurfaceController == null) {
   1339             return;
   1340         }
   1341 
   1342         final WindowState w = mWin;
   1343         final LayoutParams attrs = mWin.getAttrs();
   1344         final Task task = w.getTask();
   1345 
   1346         // We got resized, so block all updates until we got the new surface.
   1347         if (w.isResizedWhileNotDragResizing() && !w.isGoneForLayoutLw()) {
   1348             return;
   1349         }
   1350 
   1351         mTmpSize.set(w.mShownPosition.x, w.mShownPosition.y, 0, 0);
   1352         calculateSurfaceBounds(w, attrs);
   1353 
   1354         mExtraHScale = (float) 1.0;
   1355         mExtraVScale = (float) 1.0;
   1356 
   1357         boolean wasForceScaled = mForceScaleUntilResize;
   1358         boolean wasSeamlesslyRotated = w.mSeamlesslyRotated;
   1359 
   1360         // Once relayout has been called at least once, we need to make sure
   1361         // we only resize the client surface during calls to relayout. For
   1362         // clients which use indeterminate measure specs (MATCH_PARENT),
   1363         // we may try and change their window size without a call to relayout.
   1364         // However, this would be unsafe, as the client may be in the middle
   1365         // of producing a frame at the old size, having just completed layout
   1366         // to find the surface size changed underneath it.
   1367         if (!w.mRelayoutCalled || w.mInRelayout) {
   1368             mSurfaceResized = mSurfaceController.setSizeInTransaction(
   1369                     mTmpSize.width(), mTmpSize.height(), recoveringMemory);
   1370         } else {
   1371             mSurfaceResized = false;
   1372         }
   1373         mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
   1374         // If we are undergoing seamless rotation, the surface has already
   1375         // been set up to persist at it's old location. We need to freeze
   1376         // updates until a resize occurs.
   1377         mService.markForSeamlessRotation(w, w.mSeamlesslyRotated && !mSurfaceResized);
   1378 
   1379         Rect clipRect = null, finalClipRect = null;
   1380         if (calculateCrop(mTmpClipRect)) {
   1381             clipRect = mTmpClipRect;
   1382         }
   1383         if (calculateFinalCrop(mTmpFinalClipRect)) {
   1384             finalClipRect = mTmpFinalClipRect;
   1385         }
   1386 
   1387         float surfaceWidth = mSurfaceController.getWidth();
   1388         float surfaceHeight = mSurfaceController.getHeight();
   1389 
   1390         if (isForceScaled()) {
   1391             int hInsets = attrs.surfaceInsets.left + attrs.surfaceInsets.right;
   1392             int vInsets = attrs.surfaceInsets.top + attrs.surfaceInsets.bottom;
   1393             float surfaceContentWidth = surfaceWidth - hInsets;
   1394             float surfaceContentHeight = surfaceHeight - vInsets;
   1395             if (!mForceScaleUntilResize) {
   1396                 mSurfaceController.forceScaleableInTransaction(true);
   1397             }
   1398 
   1399             int posX = mTmpSize.left;
   1400             int posY = mTmpSize.top;
   1401             task.mStack.getDimBounds(mTmpStackBounds);
   1402 
   1403             boolean allowStretching = false;
   1404             task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
   1405             // If we don't have source bounds, we can attempt to use the content insets
   1406             // in the following scenario:
   1407             //    1. We have content insets.
   1408             //    2. We are not transitioning to full screen
   1409             // We have to be careful to check "lastAnimatingBoundsWasToFullscreen" rather than
   1410             // the mBoundsAnimating state, as we may have already left it and only be here
   1411             // because of the force-scale until resize state.
   1412             if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
   1413                     || mWin.mLastRelayoutContentInsets.height() > 0)
   1414                         && !task.mStack.lastAnimatingBoundsWasToFullscreen()) {
   1415                 mTmpSourceBounds.set(task.mStack.mPreAnimationBounds);
   1416                 mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
   1417                 allowStretching = true;
   1418             }
   1419             if (!mTmpSourceBounds.isEmpty()) {
   1420                 // Get the final target stack bounds, if we are not animating, this is just the
   1421                 // current stack bounds
   1422                 task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
   1423 
   1424                 // Calculate the current progress and interpolate the difference between the target
   1425                 // and source bounds
   1426                 float finalWidth = mTmpAnimatingBounds.width();
   1427                 float initialWidth = mTmpSourceBounds.width();
   1428                 float tw = (surfaceContentWidth - mTmpStackBounds.width())
   1429                         / (surfaceContentWidth - mTmpAnimatingBounds.width());
   1430                 float th = tw;
   1431                 mExtraHScale = (initialWidth + tw * (finalWidth - initialWidth)) / initialWidth;
   1432                 if (allowStretching) {
   1433                     float finalHeight = mTmpAnimatingBounds.height();
   1434                     float initialHeight = mTmpSourceBounds.height();
   1435                     th = (surfaceContentHeight - mTmpStackBounds.height())
   1436                         / (surfaceContentHeight - mTmpAnimatingBounds.height());
   1437                     mExtraVScale = (initialHeight + tw * (finalHeight - initialHeight))
   1438                             / initialHeight;
   1439                 } else {
   1440                     mExtraVScale = mExtraHScale;
   1441                 }
   1442 
   1443                 // Adjust the position to account for the inset bounds
   1444                 posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left);
   1445                 posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top);
   1446 
   1447                 // Always clip to the stack bounds since the surface can be larger with the current
   1448                 // scale
   1449                 clipRect = null;
   1450                 finalClipRect = mTmpStackBounds;
   1451             } else {
   1452                 // We want to calculate the scaling based on the content area, not based on
   1453                 // the entire surface, so that we scale in sync with windows that don't have insets.
   1454                 mExtraHScale = mTmpStackBounds.width() / surfaceContentWidth;
   1455                 mExtraVScale = mTmpStackBounds.height() / surfaceContentHeight;
   1456 
   1457                 // Since we are scaled to fit in our previously desired crop, we can now
   1458                 // expose the whole window in buffer space, and not risk extending
   1459                 // past where the system would have cropped us
   1460                 clipRect = null;
   1461                 finalClipRect = null;
   1462             }
   1463 
   1464             // In the case of ForceScaleToStack we scale entire tasks together,
   1465             // and so we need to scale our offsets relative to the task bounds
   1466             // or parent and child windows would fall out of alignment.
   1467             posX -= (int) (attrs.x * (1 - mExtraHScale));
   1468             posY -= (int) (attrs.y * (1 - mExtraVScale));
   1469 
   1470             // Imagine we are scaling down. As we scale the buffer down, we decrease the
   1471             // distance between the surface top left, and the start of the surface contents
   1472             // (previously it was surfaceInsets.left pixels in screen space but now it
   1473             // will be surfaceInsets.left*mExtraHScale). This means in order to keep the
   1474             // non inset content at the same position, we have to shift the whole window
   1475             // forward. Likewise for scaling up, we've increased this distance, and we need
   1476             // to shift by a negative number to compensate.
   1477             posX += attrs.surfaceInsets.left * (1 - mExtraHScale);
   1478             posY += attrs.surfaceInsets.top * (1 - mExtraVScale);
   1479 
   1480             mSurfaceController.setPositionInTransaction((float) Math.floor(posX),
   1481                     (float) Math.floor(posY), recoveringMemory);
   1482 
   1483             // Various surfaces in the scaled stack may resize at different times.
   1484             // We need to ensure for each surface, that we disable transformation matrix
   1485             // scaling in the same transaction which we resize the surface in.
   1486             // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
   1487             // then take over the scaling until the new buffer arrives, and things
   1488             // will be seamless.
   1489             mForceScaleUntilResize = true;
   1490         } else {
   1491             if (!w.mSeamlesslyRotated) {
   1492                 mSurfaceController.setPositionInTransaction(mTmpSize.left, mTmpSize.top,
   1493                         recoveringMemory);
   1494             }
   1495         }
   1496 
   1497         // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
   1498         // to prevent further updates until buffer latch.
   1499         // When ending both force scaling, and seamless rotation, we need to freeze
   1500         // the Surface geometry until a buffer comes in at the new size (normally position and crop
   1501         // are unfrozen). setGeometryAppliesWithResizeInTransaction accomplishes this for us.
   1502         if ((wasForceScaled && !mForceScaleUntilResize) ||
   1503                 (wasSeamlesslyRotated && !w.mSeamlesslyRotated)) {
   1504             mSurfaceController.setGeometryAppliesWithResizeInTransaction(true);
   1505             mSurfaceController.forceScaleableInTransaction(false);
   1506         }
   1507 
   1508         if (!w.mSeamlesslyRotated) {
   1509             applyCrop(clipRect, finalClipRect, recoveringMemory);
   1510             mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
   1511                     mDtDx * w.mVScale * mExtraVScale,
   1512                     mDtDy * w.mHScale * mExtraHScale,
   1513                     mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
   1514         }
   1515 
   1516         if (mSurfaceResized) {
   1517             mReportSurfaceResized = true;
   1518             mAnimator.setPendingLayoutChanges(w.getDisplayId(),
   1519                     WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER);
   1520             w.applyDimLayerIfNeeded();
   1521         }
   1522     }
   1523 
   1524     void prepareSurfaceLocked(final boolean recoveringMemory) {
   1525         final WindowState w = mWin;
   1526         if (!hasSurface()) {
   1527 
   1528             // There is no need to wait for an animation change if our window is gone for layout
   1529             // already as we'll never be visible.
   1530             if (w.mOrientationChanging && w.isGoneForLayoutLw()) {
   1531                 if (DEBUG_ORIENTATION) {
   1532                     Slog.v(TAG, "Orientation change skips hidden " + w);
   1533                 }
   1534                 w.mOrientationChanging = false;
   1535             }
   1536             return;
   1537         }
   1538 
   1539         // Do not change surface properties of opening apps if we are waiting for the
   1540         // transition to be ready. transitionGoodToGo could be not ready even after all
   1541         // opening apps are drawn. It's only waiting on isFetchingAppTransitionsSpecs()
   1542         // to get the animation spec. (For example, go into Recents and immediately open
   1543         // the same app again before the app's surface is destroyed or saved, the surface
   1544         // is always ready in the whole process.) If we go ahead here, the opening app
   1545         // will be shown with the full size before the correct animation spec arrives.
   1546         if (isWaitingForOpening()) {
   1547             return;
   1548         }
   1549 
   1550         boolean displayed = false;
   1551 
   1552         computeShownFrameLocked();
   1553 
   1554         setSurfaceBoundariesLocked(recoveringMemory);
   1555 
   1556         if (mIsWallpaper && !mWin.mWallpaperVisible) {
   1557             // Wallpaper is no longer visible and there is no wp target => hide it.
   1558             hide("prepareSurfaceLocked");
   1559         } else if (w.isParentWindowHidden() || !w.isOnScreen()) {
   1560             hide("prepareSurfaceLocked");
   1561             mWallpaperControllerLocked.hideWallpapers(w);
   1562 
   1563             // If we are waiting for this window to handle an orientation change. If this window is
   1564             // really hidden (gone for layout), there is no point in still waiting for it.
   1565             // Note that this does introduce a potential glitch if the window becomes unhidden
   1566             // before it has drawn for the new orientation.
   1567             if (w.mOrientationChanging && w.isGoneForLayoutLw()) {
   1568                 w.mOrientationChanging = false;
   1569                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   1570                         "Orientation change skips hidden " + w);
   1571             }
   1572         } else if (mLastLayer != mAnimLayer
   1573                 || mLastAlpha != mShownAlpha
   1574                 || mLastDsDx != mDsDx
   1575                 || mLastDtDx != mDtDx
   1576                 || mLastDsDy != mDsDy
   1577                 || mLastDtDy != mDtDy
   1578                 || w.mLastHScale != w.mHScale
   1579                 || w.mLastVScale != w.mVScale
   1580                 || mLastHidden) {
   1581             displayed = true;
   1582             mLastAlpha = mShownAlpha;
   1583             mLastLayer = mAnimLayer;
   1584             mLastDsDx = mDsDx;
   1585             mLastDtDx = mDtDx;
   1586             mLastDsDy = mDsDy;
   1587             mLastDtDy = mDtDy;
   1588             w.mLastHScale = w.mHScale;
   1589             w.mLastVScale = w.mVScale;
   1590             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
   1591                     "controller=" + mSurfaceController +
   1592                     "alpha=" + mShownAlpha + " layer=" + mAnimLayer
   1593                     + " matrix=[" + mDsDx + "*" + w.mHScale
   1594                     + "," + mDtDx + "*" + w.mVScale
   1595                     + "][" + mDtDy + "*" + w.mHScale
   1596                     + "," + mDsDy + "*" + w.mVScale + "]", false);
   1597 
   1598             boolean prepared =
   1599                 mSurfaceController.prepareToShowInTransaction(mShownAlpha,
   1600                         mDsDx * w.mHScale * mExtraHScale,
   1601                         mDtDx * w.mVScale * mExtraVScale,
   1602                         mDtDy * w.mHScale * mExtraHScale,
   1603                         mDsDy * w.mVScale * mExtraVScale,
   1604                         recoveringMemory);
   1605             mSurfaceController.setLayer(mAnimLayer);
   1606 
   1607             if (prepared && mLastHidden && mDrawState == HAS_DRAWN) {
   1608                 if (showSurfaceRobustlyLocked()) {
   1609                     markPreservedSurfaceForDestroy();
   1610                     mAnimator.requestRemovalOfReplacedWindows(w);
   1611                     mLastHidden = false;
   1612                     if (mIsWallpaper) {
   1613                         w.dispatchWallpaperVisibility(true);
   1614                     }
   1615                     // This draw means the difference between unique content and mirroring.
   1616                     // Run another pass through performLayout to set mHasContent in the
   1617                     // LogicalDisplay.
   1618                     mAnimator.setPendingLayoutChanges(w.getDisplayId(),
   1619                             WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM);
   1620                 } else {
   1621                     w.mOrientationChanging = false;
   1622                 }
   1623             }
   1624             if (hasSurface()) {
   1625                 w.mToken.hasVisible = true;
   1626             }
   1627         } else {
   1628             if (DEBUG_ANIM && isAnimationSet()) {
   1629                 Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
   1630             }
   1631             displayed = true;
   1632         }
   1633 
   1634         if (w.mOrientationChanging) {
   1635             if (!w.isDrawnLw()) {
   1636                 mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
   1637                 mAnimator.mLastWindowFreezeSource = w;
   1638                 if (DEBUG_ORIENTATION) Slog.v(TAG,
   1639                         "Orientation continue waiting for draw in " + w);
   1640             } else {
   1641                 w.mOrientationChanging = false;
   1642                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w);
   1643             }
   1644         }
   1645 
   1646         if (displayed) {
   1647             w.mToken.hasVisible = true;
   1648         }
   1649     }
   1650 
   1651     void setTransparentRegionHintLocked(final Region region) {
   1652         if (mSurfaceController == null) {
   1653             Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
   1654             return;
   1655         }
   1656         mSurfaceController.setTransparentRegionHint(region);
   1657     }
   1658 
   1659     void setWallpaperOffset(Point shownPosition) {
   1660         final LayoutParams attrs = mWin.getAttrs();
   1661         final int left = shownPosition.x - attrs.surfaceInsets.left;
   1662         final int top = shownPosition.y - attrs.surfaceInsets.top;
   1663 
   1664         try {
   1665             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
   1666             mService.openSurfaceTransaction();
   1667             mSurfaceController.setPositionInTransaction(mWin.mFrame.left + left,
   1668                     mWin.mFrame.top + top, false);
   1669             applyCrop(null, null, false);
   1670         } catch (RuntimeException e) {
   1671             Slog.w(TAG, "Error positioning surface of " + mWin
   1672                     + " pos=(" + left + "," + top + ")", e);
   1673         } finally {
   1674             mService.closeSurfaceTransaction();
   1675             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
   1676                     "<<< CLOSE TRANSACTION setWallpaperOffset");
   1677         }
   1678     }
   1679 
   1680     /**
   1681      * Try to change the pixel format without recreating the surface. This
   1682      * will be common in the case of changing from PixelFormat.OPAQUE to
   1683      * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
   1684      * requested formats resolve to the same underlying SurfaceControl format
   1685      * @return True if format was succesfully changed, false otherwise
   1686      */
   1687     boolean tryChangeFormatInPlaceLocked() {
   1688         if (mSurfaceController == null) {
   1689             return false;
   1690         }
   1691         final LayoutParams attrs = mWin.getAttrs();
   1692         final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
   1693         final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
   1694         if (format == mSurfaceFormat) {
   1695             setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
   1696             return true;
   1697         }
   1698         return false;
   1699     }
   1700 
   1701     void setOpaqueLocked(boolean isOpaque) {
   1702         if (mSurfaceController == null) {
   1703             return;
   1704         }
   1705         mSurfaceController.setOpaque(isOpaque);
   1706     }
   1707 
   1708     void setSecureLocked(boolean isSecure) {
   1709         if (mSurfaceController == null) {
   1710             return;
   1711         }
   1712         mSurfaceController.setSecure(isSecure);
   1713     }
   1714 
   1715     /**
   1716      * Have the surface flinger show a surface, robustly dealing with
   1717      * error conditions.  In particular, if there is not enough memory
   1718      * to show the surface, then we will try to get rid of other surfaces
   1719      * in order to succeed.
   1720      *
   1721      * @return Returns true if the surface was successfully shown.
   1722      */
   1723     private boolean showSurfaceRobustlyLocked() {
   1724         final Task task = mWin.getTask();
   1725         if (task != null && StackId.windowsAreScaleable(task.mStack.mStackId)) {
   1726             mSurfaceController.forceScaleableInTransaction(true);
   1727         }
   1728 
   1729         boolean shown = mSurfaceController.showRobustlyInTransaction();
   1730         if (!shown)
   1731             return false;
   1732 
   1733         if (mWin.mTurnOnScreen) {
   1734             if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin);
   1735             mWin.mTurnOnScreen = false;
   1736             mAnimator.mBulkUpdateParams |= SET_TURN_ON_SCREEN;
   1737         }
   1738         return true;
   1739     }
   1740 
   1741     void applyEnterAnimationLocked() {
   1742         // If we are the new part of a window replacement transition and we have requested
   1743         // not to animate, we instead want to make it seamless, so we don't want to apply
   1744         // an enter transition.
   1745         if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
   1746             return;
   1747         }
   1748         final int transit;
   1749         if (mEnterAnimationPending) {
   1750             mEnterAnimationPending = false;
   1751             transit = WindowManagerPolicy.TRANSIT_ENTER;
   1752         } else {
   1753             transit = WindowManagerPolicy.TRANSIT_SHOW;
   1754         }
   1755         applyAnimationLocked(transit, true);
   1756         //TODO (multidisplay): Magnification is supported only for the default display.
   1757         if (mService.mAccessibilityController != null
   1758                 && mWin.getDisplayId() == DEFAULT_DISPLAY) {
   1759             mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit);
   1760         }
   1761     }
   1762 
   1763     /**
   1764      * Choose the correct animation and set it to the passed WindowState.
   1765      * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn
   1766      *      then the animation will be app_starting_exit. Any other value loads the animation from
   1767      *      the switch statement below.
   1768      * @param isEntrance The animation type the last time this was called. Used to keep from
   1769      *      loading the same animation twice.
   1770      * @return true if an animation has been loaded.
   1771      */
   1772     boolean applyAnimationLocked(int transit, boolean isEntrance) {
   1773         if (mLocalAnimating && mAnimationIsEntrance == isEntrance) {
   1774             // If we are trying to apply an animation, but already running
   1775             // an animation of the same type, then just leave that one alone.
   1776             return true;
   1777         }
   1778 
   1779         // Only apply an animation if the display isn't frozen.  If it is
   1780         // frozen, there is no reason to animate and it can cause strange
   1781         // artifacts when we unfreeze the display if some different animation
   1782         // is running.
   1783         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#applyAnimationLocked");
   1784         if (mService.okToDisplay()) {
   1785             int anim = mPolicy.selectAnimationLw(mWin, transit);
   1786             int attr = -1;
   1787             Animation a = null;
   1788             if (anim != 0) {
   1789                 a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
   1790             } else {
   1791                 switch (transit) {
   1792                     case WindowManagerPolicy.TRANSIT_ENTER:
   1793                         attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
   1794                         break;
   1795                     case WindowManagerPolicy.TRANSIT_EXIT:
   1796                         attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
   1797                         break;
   1798                     case WindowManagerPolicy.TRANSIT_SHOW:
   1799                         attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
   1800                         break;
   1801                     case WindowManagerPolicy.TRANSIT_HIDE:
   1802                         attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
   1803                         break;
   1804                 }
   1805                 if (attr >= 0) {
   1806                     a = mService.mAppTransition.loadAnimationAttr(mWin.mAttrs, attr);
   1807                 }
   1808             }
   1809             if (DEBUG_ANIM) Slog.v(TAG,
   1810                     "applyAnimation: win=" + this
   1811                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
   1812                     + " a=" + a
   1813                     + " transit=" + transit
   1814                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
   1815             if (a != null) {
   1816                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
   1817                 setAnimation(a);
   1818                 mAnimationIsEntrance = isEntrance;
   1819             }
   1820         } else {
   1821             clearAnimation();
   1822         }
   1823         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
   1824 
   1825         if (mWin.mAttrs.type == TYPE_INPUT_METHOD) {
   1826             mWin.getDisplayContent().adjustForImeIfNeeded();
   1827             if (isEntrance) {
   1828                 mWin.setDisplayLayoutNeeded();
   1829                 mService.mWindowPlacerLocked.requestTraversal();
   1830             }
   1831         }
   1832         return mAnimation != null;
   1833     }
   1834 
   1835     private void applyFadeoutDuringKeyguardExitAnimation() {
   1836         long startTime = mAnimation.getStartTime();
   1837         long duration = mAnimation.getDuration();
   1838         long elapsed = mLastAnimationTime - startTime;
   1839         long fadeDuration = duration - elapsed;
   1840         if (fadeDuration <= 0) {
   1841             // Never mind, this would be no visible animation, so abort the animation change.
   1842             return;
   1843         }
   1844         AnimationSet newAnimation = new AnimationSet(false /* shareInterpolator */);
   1845         newAnimation.setDuration(duration);
   1846         newAnimation.setStartTime(startTime);
   1847         newAnimation.addAnimation(mAnimation);
   1848         Animation fadeOut = AnimationUtils.loadAnimation(
   1849                 mContext, com.android.internal.R.anim.app_starting_exit);
   1850         fadeOut.setDuration(fadeDuration);
   1851         fadeOut.setStartOffset(elapsed);
   1852         newAnimation.addAnimation(fadeOut);
   1853         newAnimation.initialize(mWin.mFrame.width(), mWin.mFrame.height(), mAnimDx, mAnimDy);
   1854         mAnimation = newAnimation;
   1855     }
   1856 
   1857     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
   1858         if (mAnimating || mLocalAnimating || mAnimationIsEntrance
   1859                 || mAnimation != null) {
   1860             pw.print(prefix); pw.print("mAnimating="); pw.print(mAnimating);
   1861                     pw.print(" mLocalAnimating="); pw.print(mLocalAnimating);
   1862                     pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
   1863                     pw.print(" mAnimation="); pw.print(mAnimation);
   1864                     pw.print(" mStackClip="); pw.println(mStackClip);
   1865         }
   1866         if (mHasTransformation || mHasLocalTransformation) {
   1867             pw.print(prefix); pw.print("XForm: has=");
   1868                     pw.print(mHasTransformation);
   1869                     pw.print(" hasLocal="); pw.print(mHasLocalTransformation);
   1870                     pw.print(" "); mTransformation.printShortString(pw);
   1871                     pw.println();
   1872         }
   1873         if (mSurfaceController != null) {
   1874             mSurfaceController.dump(pw, prefix, dumpAll);
   1875         }
   1876         if (dumpAll) {
   1877             pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString());
   1878             pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden);
   1879             pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
   1880             pw.print(" last="); mLastSystemDecorRect.printShortString(pw);
   1881             pw.print(" mHasClipRect="); pw.print(mHasClipRect);
   1882             pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw);
   1883 
   1884             if (!mLastFinalClipRect.isEmpty()) {
   1885                 pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw);
   1886             }
   1887             pw.println();
   1888         }
   1889 
   1890         if (mPendingDestroySurface != null) {
   1891             pw.print(prefix); pw.print("mPendingDestroySurface=");
   1892                     pw.println(mPendingDestroySurface);
   1893         }
   1894         if (mSurfaceResized || mSurfaceDestroyDeferred) {
   1895             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
   1896                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
   1897         }
   1898         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
   1899             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
   1900                     pw.print(" mAlpha="); pw.print(mAlpha);
   1901                     pw.print(" mLastAlpha="); pw.println(mLastAlpha);
   1902         }
   1903         if (mHaveMatrix || mWin.mGlobalScale != 1) {
   1904             pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
   1905                     pw.print(" mDsDx="); pw.print(mDsDx);
   1906                     pw.print(" mDtDx="); pw.print(mDtDx);
   1907                     pw.print(" mDtDy="); pw.print(mDtDy);
   1908                     pw.print(" mDsDy="); pw.println(mDsDy);
   1909         }
   1910         if (mAnimationStartDelayed) {
   1911             pw.print(prefix); pw.print("mAnimationStartDelayed="); pw.print(mAnimationStartDelayed);
   1912         }
   1913     }
   1914 
   1915     @Override
   1916     public String toString() {
   1917         StringBuffer sb = new StringBuffer("WindowStateAnimator{");
   1918         sb.append(Integer.toHexString(System.identityHashCode(this)));
   1919         sb.append(' ');
   1920         sb.append(mWin.mAttrs.getTitle());
   1921         sb.append('}');
   1922         return sb.toString();
   1923     }
   1924 
   1925     void reclaimSomeSurfaceMemory(String operation, boolean secure) {
   1926         mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure);
   1927     }
   1928 
   1929     boolean getShown() {
   1930         if (mSurfaceController != null) {
   1931             return mSurfaceController.getShown();
   1932         }
   1933         return false;
   1934     }
   1935 
   1936     void destroySurface() {
   1937         try {
   1938             if (mSurfaceController != null) {
   1939                 mSurfaceController.destroyInTransaction();
   1940             }
   1941         } catch (RuntimeException e) {
   1942             Slog.w(TAG, "Exception thrown when destroying surface " + this
   1943                     + " surface " + mSurfaceController + " session " + mSession + ": " + e);
   1944         } finally {
   1945             mWin.setHasSurface(false);
   1946             mSurfaceController = null;
   1947             mDrawState = NO_SURFACE;
   1948         }
   1949     }
   1950 
   1951     void setMoveAnimation(int left, int top) {
   1952         final Animation a = AnimationUtils.loadAnimation(mContext,
   1953                 com.android.internal.R.anim.window_move_from_decor);
   1954         setAnimation(a);
   1955         mAnimDx = mWin.mLastFrame.left - left;
   1956         mAnimDy = mWin.mLastFrame.top - top;
   1957         mAnimateMove = true;
   1958     }
   1959 
   1960     void deferTransactionUntilParentFrame(long frameNumber) {
   1961         if (!mWin.isChildWindow()) {
   1962             return;
   1963         }
   1964         mSurfaceController.deferTransactionUntil(
   1965                 mWin.getParentWindow().mWinAnimator.mSurfaceController.getHandle(), frameNumber);
   1966     }
   1967 
   1968     /**
   1969      * Sometimes we need to synchronize the first frame of animation with some external event.
   1970      * To achieve this, we prolong the start of the animation and keep producing the first frame of
   1971      * the animation.
   1972      */
   1973     private long getAnimationFrameTime(Animation animation, long currentTime) {
   1974         if (mAnimationStartDelayed) {
   1975             animation.setStartTime(currentTime);
   1976             return currentTime + 1;
   1977         }
   1978         return currentTime;
   1979     }
   1980 
   1981     void startDelayingAnimationStart() {
   1982         mAnimationStartDelayed = true;
   1983     }
   1984 
   1985     void endDelayingAnimationStart() {
   1986         mAnimationStartDelayed = false;
   1987     }
   1988 
   1989     void seamlesslyRotateWindow(int oldRotation, int newRotation) {
   1990         final WindowState w = mWin;
   1991         if (!w.isVisibleNow() || w.mIsWallpaper) {
   1992             return;
   1993         }
   1994 
   1995         final Rect cropRect = mService.mTmpRect;
   1996         final Rect displayRect = mService.mTmpRect2;
   1997         final RectF frameRect = mService.mTmpRectF;
   1998         final Matrix transform = mService.mTmpTransform;
   1999 
   2000         final float x = w.mFrame.left;
   2001         final float y = w.mFrame.top;
   2002         final float width = w.mFrame.width();
   2003         final float height = w.mFrame.height();
   2004 
   2005         mService.getDefaultDisplayContentLocked().getLogicalDisplayRect(displayRect);
   2006         final float displayWidth = displayRect.width();
   2007         final float displayHeight = displayRect.height();
   2008 
   2009         // Compute a transform matrix to undo the coordinate space transformation,
   2010         // and present the window at the same physical position it previously occupied.
   2011         final int deltaRotation = DisplayContent.deltaRotation(newRotation, oldRotation);
   2012         DisplayContent.createRotationMatrix(deltaRotation, x, y, displayWidth, displayHeight,
   2013                 transform);
   2014 
   2015         // We just need to apply a rotation matrix to the window. For example
   2016         // if we have a portrait window and rotate to landscape, the window is still portrait
   2017         // and now extends off the bottom of the screen (and only halfway across). Essentially we
   2018         // apply a transform to display the current buffer at it's old position
   2019         // (in the new coordinate space). We then freeze layer updates until the resize
   2020         // occurs, at which point we undo, them.
   2021         mService.markForSeamlessRotation(w, true);
   2022         transform.getValues(mService.mTmpFloats);
   2023 
   2024         float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
   2025         float DtDx = mService.mTmpFloats[Matrix.MSKEW_Y];
   2026         float DtDy = mService.mTmpFloats[Matrix.MSKEW_X];
   2027         float DsDy = mService.mTmpFloats[Matrix.MSCALE_Y];
   2028         float nx = mService.mTmpFloats[Matrix.MTRANS_X];
   2029         float ny = mService.mTmpFloats[Matrix.MTRANS_Y];
   2030         mSurfaceController.setPositionInTransaction(nx, ny, false);
   2031         mSurfaceController.setMatrixInTransaction(DsDx * w.mHScale,
   2032                 DtDx * w.mVScale,
   2033                 DtDy * w.mHScale,
   2034                 DsDy * w.mVScale, false);
   2035     }
   2036 
   2037     void enableSurfaceTrace(FileDescriptor fd) {
   2038         if (mSurfaceController != null) {
   2039             mSurfaceController.installRemoteTrace(fd);
   2040         }
   2041     }
   2042 
   2043     void disableSurfaceTrace() {
   2044         if (mSurfaceController != null) {
   2045             try {
   2046                 mSurfaceController.removeRemoteTrace();
   2047             } catch (ClassCastException e) {
   2048                 Slog.e(TAG, "Disable surface trace for " + this + " but its not enabled");
   2049             }
   2050         }
   2051     }
   2052 
   2053     /** The force-scaled state for a given window can persist past
   2054      * the state for it's stack as the windows complete resizing
   2055      * independently of one another.
   2056      */
   2057     boolean isForceScaled() {
   2058         final Task task = mWin.getTask();
   2059         if (task != null && task.mStack.isForceScaled()) {
   2060             return true;
   2061         }
   2062         return mForceScaleUntilResize;
   2063     }
   2064 
   2065     void detachChildren() {
   2066         if (mSurfaceController != null) {
   2067             mSurfaceController.detachChildren();
   2068         }
   2069     }
   2070 }
   2071