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