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