OSDN Git Service

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