1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.view.Display.DEFAULT_DISPLAY;
20 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
21 import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
22 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
23 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
24 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
25 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
26 import static android.view.WindowManager.TRANSIT_NONE;
27 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
28 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
29 import static com.android.server.wm.DragResizeMode.DRAG_RESIZE_MODE_FREEFORM;
30 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
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_STARTING_WINDOW_VERBOSE;
35 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_CROP;
37 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
38 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
39 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
40 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
41 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
42 import static com.android.server.wm.WindowManagerService.TYPE_LAYER_MULTIPLIER;
43 import static com.android.server.wm.WindowManagerService.logWithStack;
44 import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
45 import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
46 import static com.android.server.wm.WindowStateAnimatorProto.LAST_CLIP_RECT;
47 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
48 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
49 
50 import android.content.Context;
51 import android.graphics.Matrix;
52 import android.graphics.PixelFormat;
53 import android.graphics.Point;
54 import android.graphics.Rect;
55 import android.graphics.RectF;
56 import android.graphics.Region;
57 import android.os.Debug;
58 import android.os.Trace;
59 import android.util.Slog;
60 import android.util.proto.ProtoOutputStream;
61 import android.view.DisplayInfo;
62 import android.view.Surface.OutOfResourcesException;
63 import android.view.SurfaceControl;
64 import android.view.WindowManager;
65 import android.view.WindowManager.LayoutParams;
66 import android.view.animation.Animation;
67 import android.view.animation.AnimationUtils;
68 
69 import com.android.server.policy.WindowManagerPolicy;
70 
71 import java.io.PrintWriter;
72 
73 /**
74  * Keep track of animations and surface operations for a single WindowState.
75  **/
76 class WindowStateAnimator {
77     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
78     static final int WINDOW_FREEZE_LAYER = TYPE_LAYER_MULTIPLIER * 200;
79 
80     /**
81      * Mode how the window gets clipped by the stack bounds during an animation: The clipping should
82      * be applied after applying the animation transformation, i.e. the stack bounds don't move
83      * during the animation.
84      */
85     static final int STACK_CLIP_AFTER_ANIM = 0;
86 
87     /**
88      * Mode how the window gets clipped by the stack bounds: The clipping should be applied before
89      * applying the animation transformation, i.e. the stack bounds move with the window.
90      */
91     static final int STACK_CLIP_BEFORE_ANIM = 1;
92 
93     /**
94      * Mode how window gets clipped by the stack bounds during an animation: Don't clip the window
95      * by the stack bounds.
96      */
97     static final int STACK_CLIP_NONE = 2;
98 
99     // Unchanging local convenience fields.
100     final WindowManagerService mService;
101     final WindowState mWin;
102     final WindowAnimator mAnimator;
103     final Session mSession;
104     final WindowManagerPolicy mPolicy;
105     final Context mContext;
106     final boolean mIsWallpaper;
107     private final WallpaperController mWallpaperControllerLocked;
108 
109     boolean mAnimationIsEntrance;
110     int mAnimLayer;
111     int mLastLayer;
112 
113     /**
114      * Set when we have changed the size of the surface, to know that
115      * we must tell them application to resize (and thus redraw itself).
116      */
117     boolean mSurfaceResized;
118     /**
119      * Whether we should inform the client on next relayoutWindow that
120      * the surface has been resized since last time.
121      */
122     boolean mReportSurfaceResized;
123     WindowSurfaceController mSurfaceController;
124     private WindowSurfaceController mPendingDestroySurface;
125 
126     /**
127      * Set if the client has asked that the destroy of its surface be delayed
128      * until it explicitly says it is okay.
129      */
130     boolean mSurfaceDestroyDeferred;
131 
132     private boolean mDestroyPreservedSurfaceUponRedraw;
133     float mShownAlpha = 0;
134     float mAlpha = 0;
135     float mLastAlpha = 0;
136 
137     Rect mTmpClipRect = new Rect();
138     Rect mTmpFinalClipRect = new Rect();
139     Rect mLastClipRect = new Rect();
140     Rect mLastFinalClipRect = new Rect();
141     Rect mTmpStackBounds = new Rect();
142     private Rect mTmpAnimatingBounds = new Rect();
143     private Rect mTmpSourceBounds = new Rect();
144 
145     /**
146      * This is rectangle of the window's surface that is not covered by
147      * system decorations.
148      */
149     private final Rect mSystemDecorRect = new Rect();
150 
151     float mDsDx=1, mDtDx=0, mDsDy=0, mDtDy=1;
152     private float mLastDsDx=1, mLastDtDx=0, mLastDsDy=0, mLastDtDy=1;
153 
154     boolean mHaveMatrix;
155 
156     // Set to true if, when the window gets displayed, it should perform
157     // an enter animation.
158     boolean mEnterAnimationPending;
159 
160     /** Used to indicate that this window is undergoing an enter animation. Used for system
161      * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
162      * window is first added or shown, cleared when the callback has been made. */
163     boolean mEnteringAnimation;
164 
165     private boolean mAnimationStartDelayed;
166 
167     private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
168 
169     /** The pixel format of the underlying SurfaceControl */
170     int mSurfaceFormat;
171 
172     /** This is set when there is no Surface */
173     static final int NO_SURFACE = 0;
174     /** This is set after the Surface has been created but before the window has been drawn. During
175      * this time the surface is hidden. */
176     static final int DRAW_PENDING = 1;
177     /** This is set after the window has finished drawing for the first time but before its surface
178      * is shown.  The surface will be displayed when the next layout is run. */
179     static final int COMMIT_DRAW_PENDING = 2;
180     /** This is set during the time after the window's drawing has been committed, and before its
181      * surface is actually shown.  It is used to delay showing the surface until all windows in a
182      * token are ready to be shown. */
183     static final int READY_TO_SHOW = 3;
184     /** Set when the window has been shown in the screen the first time. */
185     static final int HAS_DRAWN = 4;
186 
drawStateToString()187     String drawStateToString() {
188         switch (mDrawState) {
189             case NO_SURFACE: return "NO_SURFACE";
190             case DRAW_PENDING: return "DRAW_PENDING";
191             case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
192             case READY_TO_SHOW: return "READY_TO_SHOW";
193             case HAS_DRAWN: return "HAS_DRAWN";
194             default: return Integer.toString(mDrawState);
195         }
196     }
197     int mDrawState;
198 
199     /** Was this window last hidden? */
200     boolean mLastHidden;
201 
202     int mAttrType;
203 
204     boolean mForceScaleUntilResize;
205 
206     // WindowState.mHScale and WindowState.mVScale contain the
207     // scale according to client specified layout parameters (e.g.
208     // one layout size, with another surface size, creates such scaling).
209     // Here we track an additional scaling factor used to follow stack
210     // scaling (as in the case of the Pinned stack animation).
211     float mExtraHScale = (float) 1.0;
212     float mExtraVScale = (float) 1.0;
213 
214     // An offset in pixel of the surface contents from the window position. Used for Wallpaper
215     // to provide the effect of scrolling within a large surface. We just use these values as
216     // a cache.
217     int mXOffset = 0;
218     int mYOffset = 0;
219 
220     /**
221      * A flag to determine if the WSA needs to offset its position to compensate for the stack's
222      * position update before the WSA surface has resized.
223      */
224     private boolean mOffsetPositionForStackResize;
225 
226     private final Rect mTmpSize = new Rect();
227 
228     private final SurfaceControl.Transaction mReparentTransaction = new SurfaceControl.Transaction();
229 
230     // Used to track whether we have called detach children on the way to invisibility, in which
231     // case we need to give the client a new Surface if it lays back out to a visible state.
232     boolean mChildrenDetached = false;
233 
234     // Set to true after the first frame of the Pinned stack animation
235     // and reset after the last to ensure we only reset mForceScaleUntilResize
236     // once per animation.
237     boolean mPipAnimationStarted = false;
238 
239     private final Point mTmpPos = new Point();
240 
WindowStateAnimator(final WindowState win)241     WindowStateAnimator(final WindowState win) {
242         final WindowManagerService service = win.mService;
243 
244         mService = service;
245         mAnimator = service.mAnimator;
246         mPolicy = service.mPolicy;
247         mContext = service.mContext;
248 
249         mWin = win;
250         mSession = win.mSession;
251         mAttrType = win.mAttrs.type;
252         mIsWallpaper = win.mIsWallpaper;
253         mWallpaperControllerLocked = mService.mRoot.mWallpaperController;
254     }
255 
256     /**
257      * Is the window or its container currently set to animate or currently animating?
258      */
isAnimationSet()259     boolean isAnimationSet() {
260         return mWin.isAnimating();
261     }
262 
cancelExitAnimationForNextAnimationLocked()263     void cancelExitAnimationForNextAnimationLocked() {
264         if (DEBUG_ANIM) Slog.d(TAG,
265                 "cancelExitAnimationForNextAnimationLocked: " + mWin);
266 
267         mWin.cancelAnimation();
268         mWin.destroySurfaceUnchecked();
269     }
270 
onAnimationFinished()271     void onAnimationFinished() {
272         // Done animating, clean up.
273         if (DEBUG_ANIM) Slog.v(
274                 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
275                         + ", reportedVisible="
276                         + (mWin.mAppToken != null ? mWin.mAppToken.reportedVisible : false));
277 
278         if (mAnimator.mWindowDetachedWallpaper == mWin) {
279             mAnimator.mWindowDetachedWallpaper = null;
280         }
281 
282         mWin.checkPolicyVisibilityChange();
283         final DisplayContent displayContent = mWin.getDisplayContent();
284         if (mAttrType == LayoutParams.TYPE_STATUS_BAR && mWin.mPolicyVisibility) {
285             // Upon completion of a not-visible to visible status bar animation a relayout is
286             // required.
287             if (displayContent != null) {
288                 displayContent.setLayoutNeeded();
289             }
290         }
291 
292         mWin.onExitAnimationDone();
293         final int displayId = mWin.getDisplayId();
294         int pendingLayoutChanges = FINISH_LAYOUT_REDO_ANIM;
295         if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) {
296             pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
297         }
298         mAnimator.setPendingLayoutChanges(displayId, pendingLayoutChanges);
299         if (DEBUG_LAYOUT_REPEATS)
300             mService.mWindowPlacerLocked.debugLayoutRepeats(
301                     "WindowStateAnimator", mAnimator.getPendingLayoutChanges(displayId));
302 
303         if (mWin.mAppToken != null) {
304             mWin.mAppToken.updateReportedVisibilityLocked();
305         }
306     }
307 
hide(SurfaceControl.Transaction transaction, String reason)308     void hide(SurfaceControl.Transaction transaction, String reason) {
309         if (!mLastHidden) {
310             //dump();
311             mLastHidden = true;
312 
313             // We may have a preserved surface which we no longer need. If there was a quick
314             // VISIBLE, GONE, VISIBLE, GONE sequence, the surface may never draw, so we don't mark
315             // it to be destroyed in prepareSurfaceLocked.
316             markPreservedSurfaceForDestroy();
317 
318             if (mSurfaceController != null) {
319                 mSurfaceController.hide(transaction, reason);
320             }
321         }
322     }
323 
hide(String reason)324     void hide(String reason) {
325         hide(mTmpTransaction, reason);
326         SurfaceControl.mergeToGlobalTransaction(mTmpTransaction);
327     }
328 
finishDrawingLocked()329     boolean finishDrawingLocked() {
330         final boolean startingWindow =
331                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
332         if (DEBUG_STARTING_WINDOW && startingWindow) {
333             Slog.v(TAG, "Finishing drawing window " + mWin + ": mDrawState="
334                     + drawStateToString());
335         }
336 
337         boolean layoutNeeded = false;
338 
339         if (mDrawState == DRAW_PENDING) {
340             if (DEBUG_ANIM || SHOW_TRANSACTIONS || DEBUG_ORIENTATION)
341                 Slog.v(TAG, "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING " + mWin + " in "
342                         + mSurfaceController);
343             if (DEBUG_STARTING_WINDOW && startingWindow) {
344                 Slog.v(TAG, "Draw state now committed in " + mWin);
345             }
346             mDrawState = COMMIT_DRAW_PENDING;
347             layoutNeeded = true;
348         }
349 
350         return layoutNeeded;
351     }
352 
353     // This must be called while inside a transaction.
commitFinishDrawingLocked()354     boolean commitFinishDrawingLocked() {
355         if (DEBUG_STARTING_WINDOW_VERBOSE &&
356                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
357             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
358                     + drawStateToString());
359         }
360         if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
361             return false;
362         }
363         if (DEBUG_ANIM) {
364             Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController);
365         }
366         mDrawState = READY_TO_SHOW;
367         boolean result = false;
368         final AppWindowToken atoken = mWin.mAppToken;
369         if (atoken == null || atoken.allDrawn || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
370             result = mWin.performShowLocked();
371         }
372         return result;
373     }
374 
preserveSurfaceLocked()375     void preserveSurfaceLocked() {
376         if (mDestroyPreservedSurfaceUponRedraw) {
377             // This could happen when switching the surface mode very fast. For example,
378             // we preserved a surface when dragResizing changed to true. Then before the
379             // preserved surface is removed, dragResizing changed to false again.
380             // In this case, we need to leave the preserved surface alone, and destroy
381             // the actual surface, so that the createSurface call could create a surface
382             // of the proper size. The preserved surface will still be removed when client
383             // finishes drawing to the new surface.
384             mSurfaceDestroyDeferred = false;
385             destroySurfaceLocked();
386             mSurfaceDestroyDeferred = true;
387             return;
388         }
389         if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin, "SET FREEZE LAYER", false);
390         if (mSurfaceController != null) {
391             // Our SurfaceControl is always at layer 0 within the parent Surface managed by
392             // window-state. We want this old Surface to stay on top of the new one
393             // until we do the swap, so we place it at layer 1.
394             mSurfaceController.mSurfaceControl.setLayer(1);
395         }
396         mDestroyPreservedSurfaceUponRedraw = true;
397         mSurfaceDestroyDeferred = true;
398         destroySurfaceLocked();
399     }
400 
destroyPreservedSurfaceLocked()401     void destroyPreservedSurfaceLocked() {
402         if (!mDestroyPreservedSurfaceUponRedraw) {
403             return;
404         }
405         if (mSurfaceController != null) {
406             if (mPendingDestroySurface != null) {
407                 // If we are preserving a surface but we aren't relaunching that means
408                 // we are just doing an in-place switch. In that case any SurfaceFlinger side
409                 // child layers need to be reparented to the new surface to make this
410                 // transparent to the app.
411                 if (mWin.mAppToken == null || mWin.mAppToken.isRelaunching() == false) {
412                     mReparentTransaction.reparentChildren(mPendingDestroySurface.mSurfaceControl,
413                             mSurfaceController.mSurfaceControl.getHandle())
414                             .apply();
415                 }
416             }
417         }
418 
419         destroyDeferredSurfaceLocked();
420         mDestroyPreservedSurfaceUponRedraw = false;
421     }
422 
markPreservedSurfaceForDestroy()423     void markPreservedSurfaceForDestroy() {
424         if (mDestroyPreservedSurfaceUponRedraw
425                 && !mService.mDestroyPreservedSurface.contains(mWin)) {
426             mService.mDestroyPreservedSurface.add(mWin);
427         }
428     }
429 
getLayerStack()430     private int getLayerStack() {
431         return mWin.getDisplayContent().getDisplay().getLayerStack();
432     }
433 
resetDrawState()434     void resetDrawState() {
435         mDrawState = DRAW_PENDING;
436 
437         if (mWin.mAppToken == null) {
438             return;
439         }
440 
441         if (!mWin.mAppToken.isSelfAnimating()) {
442             mWin.mAppToken.clearAllDrawn();
443         } else {
444             // Currently animating, persist current state of allDrawn until animation
445             // is complete.
446             mWin.mAppToken.deferClearAllDrawn = true;
447         }
448     }
449 
createSurfaceLocked(int windowType, int ownerUid)450     WindowSurfaceController createSurfaceLocked(int windowType, int ownerUid) {
451         final WindowState w = mWin;
452 
453         if (mSurfaceController != null) {
454             return mSurfaceController;
455         }
456         mChildrenDetached = false;
457 
458         if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {
459             windowType = SurfaceControl.WINDOW_TYPE_DONT_SCREENSHOT;
460         }
461 
462         w.setHasSurface(false);
463 
464         if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
465                 "createSurface " + this + ": mDrawState=DRAW_PENDING");
466 
467         resetDrawState();
468 
469         mService.makeWindowFreezingScreenIfNeededLocked(w);
470 
471         int flags = SurfaceControl.HIDDEN;
472         final WindowManager.LayoutParams attrs = w.mAttrs;
473 
474         if (mService.isSecureLocked(w)) {
475             flags |= SurfaceControl.SECURE;
476         }
477 
478         mTmpSize.set(0, 0, 0, 0);
479         calculateSurfaceBounds(w, attrs);
480         final int width = mTmpSize.width();
481         final int height = mTmpSize.height();
482 
483         if (DEBUG_VISIBILITY) {
484             Slog.v(TAG, "Creating surface in session "
485                     + mSession.mSurfaceSession + " window " + this
486                     + " w=" + width + " h=" + height
487                     + " x=" + mTmpSize.left + " y=" + mTmpSize.top
488                     + " format=" + attrs.format + " flags=" + flags);
489         }
490 
491         // We may abort, so initialize to defaults.
492         mLastClipRect.set(0, 0, 0, 0);
493 
494         // Set up surface control with initial size.
495         try {
496 
497             final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
498             final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
499             if (!PixelFormat.formatHasAlpha(attrs.format)
500                     // Don't make surface with surfaceInsets opaque as they display a
501                     // translucent shadow.
502                     && attrs.surfaceInsets.left == 0
503                     && attrs.surfaceInsets.top == 0
504                     && attrs.surfaceInsets.right == 0
505                     && attrs.surfaceInsets.bottom == 0
506                     // Don't make surface opaque when resizing to reduce the amount of
507                     // artifacts shown in areas the app isn't drawing content to.
508                     && !w.isDragResizing()) {
509                 flags |= SurfaceControl.OPAQUE;
510             }
511 
512             mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
513                     attrs.getTitle().toString(), width, height, format, flags, this,
514                     windowType, ownerUid);
515 
516             setOffsetPositionForStackResize(false);
517             mSurfaceFormat = format;
518 
519             w.setHasSurface(true);
520 
521             if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
522                 Slog.i(TAG, "  CREATE SURFACE "
523                         + mSurfaceController + " IN SESSION "
524                         + mSession.mSurfaceSession
525                         + ": pid=" + mSession.mPid + " format="
526                         + attrs.format + " flags=0x"
527                         + Integer.toHexString(flags)
528                         + " / " + this);
529             }
530         } catch (OutOfResourcesException e) {
531             Slog.w(TAG, "OutOfResourcesException creating surface");
532             mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
533             mDrawState = NO_SURFACE;
534             return null;
535         } catch (Exception e) {
536             Slog.e(TAG, "Exception creating surface (parent dead?)", e);
537             mDrawState = NO_SURFACE;
538             return null;
539         }
540 
541         if (WindowManagerService.localLOGV) Slog.v(TAG, "Got surface: " + mSurfaceController
542                 + ", set left=" + w.mFrame.left + " top=" + w.mFrame.top
543                 + ", animLayer=" + mAnimLayer);
544 
545         if (SHOW_LIGHT_TRANSACTIONS) {
546             Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
547             WindowManagerService.logSurface(w, "CREATE pos=("
548                     + w.mFrame.left + "," + w.mFrame.top + ") ("
549                     + width + "x" + height + "), layer=" + mAnimLayer + " HIDE", false);
550         }
551 
552         mLastHidden = true;
553 
554         if (WindowManagerService.localLOGV) Slog.v(TAG, "Created surface " + this);
555         return mSurfaceController;
556     }
557 
calculateSurfaceBounds(WindowState w, LayoutParams attrs)558     private void calculateSurfaceBounds(WindowState w, LayoutParams attrs) {
559         if ((attrs.flags & FLAG_SCALED) != 0) {
560             // For a scaled surface, we always want the requested size.
561             mTmpSize.right = mTmpSize.left + w.mRequestedWidth;
562             mTmpSize.bottom = mTmpSize.top + w.mRequestedHeight;
563         } else {
564             // When we're doing a drag-resizing, request a surface that's fullscreen size,
565             // so that we don't need to reallocate during the process. This also prevents
566             // buffer drops due to size mismatch.
567             if (w.isDragResizing()) {
568                 if (w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM) {
569                     mTmpSize.left = 0;
570                     mTmpSize.top = 0;
571                 }
572                 final DisplayInfo displayInfo = w.getDisplayInfo();
573                 mTmpSize.right = mTmpSize.left + displayInfo.logicalWidth;
574                 mTmpSize.bottom = mTmpSize.top + displayInfo.logicalHeight;
575             } else {
576                 mTmpSize.right = mTmpSize.left + w.mCompatFrame.width();
577                 mTmpSize.bottom = mTmpSize.top + w.mCompatFrame.height();
578             }
579         }
580 
581         // Something is wrong and SurfaceFlinger will not like this, try to revert to sane values.
582         // This doesn't necessarily mean that there is an error in the system. The sizes might be
583         // incorrect, because it is before the first layout or draw.
584         if (mTmpSize.width() < 1) {
585             mTmpSize.right = mTmpSize.left + 1;
586         }
587         if (mTmpSize.height() < 1) {
588             mTmpSize.bottom = mTmpSize.top + 1;
589         }
590 
591         // Adjust for surface insets.
592         mTmpSize.left -= attrs.surfaceInsets.left;
593         mTmpSize.top -= attrs.surfaceInsets.top;
594         mTmpSize.right += attrs.surfaceInsets.right;
595         mTmpSize.bottom += attrs.surfaceInsets.bottom;
596     }
597 
hasSurface()598     boolean hasSurface() {
599         return mSurfaceController != null && mSurfaceController.hasSurface();
600     }
601 
destroySurfaceLocked()602     void destroySurfaceLocked() {
603         final AppWindowToken wtoken = mWin.mAppToken;
604         if (wtoken != null) {
605             if (mWin == wtoken.startingWindow) {
606                 wtoken.startingDisplayed = false;
607             }
608         }
609 
610         if (mSurfaceController == null) {
611             return;
612         }
613 
614         // When destroying a surface we want to make sure child windows are hidden. If we are
615         // preserving the surface until redraw though we intend to swap it out with another surface
616         // for resizing. In this case the window always remains visible to the user and the child
617         // windows should likewise remain visible.
618         if (!mDestroyPreservedSurfaceUponRedraw) {
619             mWin.mHidden = true;
620         }
621 
622         try {
623             if (DEBUG_VISIBILITY) logWithStack(TAG, "Window " + this + " destroying surface "
624                     + mSurfaceController + ", session " + mSession);
625             if (mSurfaceDestroyDeferred) {
626                 if (mSurfaceController != null && mPendingDestroySurface != mSurfaceController) {
627                     if (mPendingDestroySurface != null) {
628                         if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
629                             WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
630                         }
631                         mPendingDestroySurface.destroyNotInTransaction();
632                     }
633                     mPendingDestroySurface = mSurfaceController;
634                 }
635             } else {
636                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
637                     WindowManagerService.logSurface(mWin, "DESTROY", true);
638                 }
639                 destroySurface();
640             }
641             // Don't hide wallpaper if we're deferring the surface destroy
642             // because of a surface change.
643             if (!mDestroyPreservedSurfaceUponRedraw) {
644                 mWallpaperControllerLocked.hideWallpapers(mWin);
645             }
646         } catch (RuntimeException e) {
647             Slog.w(TAG, "Exception thrown when destroying Window " + this
648                 + " surface " + mSurfaceController + " session " + mSession + ": " + e.toString());
649         }
650 
651         // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it
652         // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary
653         // so it can be recreated successfully in mPendingDestroySurface case.
654         mWin.setHasSurface(false);
655         if (mSurfaceController != null) {
656             mSurfaceController.setShown(false);
657         }
658         mSurfaceController = null;
659         mDrawState = NO_SURFACE;
660     }
661 
destroyDeferredSurfaceLocked()662     void destroyDeferredSurfaceLocked() {
663         try {
664             if (mPendingDestroySurface != null) {
665                 if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) {
666                     WindowManagerService.logSurface(mWin, "DESTROY PENDING", true);
667                 }
668                 mPendingDestroySurface.destroyNotInTransaction();
669                 // Don't hide wallpaper if we're destroying a deferred surface
670                 // after a surface mode change.
671                 if (!mDestroyPreservedSurfaceUponRedraw) {
672                     mWallpaperControllerLocked.hideWallpapers(mWin);
673                 }
674             }
675         } catch (RuntimeException e) {
676             Slog.w(TAG, "Exception thrown when destroying Window "
677                     + this + " surface " + mPendingDestroySurface
678                     + " session " + mSession + ": " + e.toString());
679         }
680         mSurfaceDestroyDeferred = false;
681         mPendingDestroySurface = null;
682     }
683 
computeShownFrameLocked()684     void computeShownFrameLocked() {
685         final int displayId = mWin.getDisplayId();
686         final ScreenRotationAnimation screenRotationAnimation =
687                 mAnimator.getScreenRotationAnimationLocked(displayId);
688         final boolean screenAnimation =
689                 screenRotationAnimation != null && screenRotationAnimation.isAnimating();
690 
691         if (screenAnimation) {
692             // cache often used attributes locally
693             final Rect frame = mWin.mFrame;
694             final float tmpFloats[] = mService.mTmpFloats;
695             final Matrix tmpMatrix = mWin.mTmpMatrix;
696 
697             // Compute the desired transformation.
698             if (screenRotationAnimation.isRotating()) {
699                 // If we are doing a screen animation, the global rotation
700                 // applied to windows can result in windows that are carefully
701                 // aligned with each other to slightly separate, allowing you
702                 // to see what is behind them.  An unsightly mess.  This...
703                 // thing...  magically makes it call good: scale each window
704                 // slightly (two pixels larger in each dimension, from the
705                 // window's center).
706                 final float w = frame.width();
707                 final float h = frame.height();
708                 if (w>=1 && h>=1) {
709                     tmpMatrix.setScale(1 + 2/w, 1 + 2/h, w/2, h/2);
710                 } else {
711                     tmpMatrix.reset();
712                 }
713             } else {
714                 tmpMatrix.reset();
715             }
716 
717             tmpMatrix.postScale(mWin.mGlobalScale, mWin.mGlobalScale);
718 
719             // WindowState.prepareSurfaces expands for surface insets (in order they don't get
720             // clipped by the WindowState surface), so we need to go into the other direction here.
721             tmpMatrix.postTranslate(mWin.mAttrs.surfaceInsets.left,
722                     mWin.mAttrs.surfaceInsets.top);
723 
724 
725             // "convert" it into SurfaceFlinger's format
726             // (a 2x2 matrix + an offset)
727             // Here we must not transform the position of the surface
728             // since it is already included in the transformation.
729             //Slog.i(TAG_WM, "Transform: " + matrix);
730 
731             mHaveMatrix = true;
732             tmpMatrix.getValues(tmpFloats);
733             mDsDx = tmpFloats[Matrix.MSCALE_X];
734             mDtDx = tmpFloats[Matrix.MSKEW_Y];
735             mDtDy = tmpFloats[Matrix.MSKEW_X];
736             mDsDy = tmpFloats[Matrix.MSCALE_Y];
737 
738             // Now set the alpha...  but because our current hardware
739             // can't do alpha transformation on a non-opaque surface,
740             // turn it off if we are running an animation that is also
741             // transforming since it is more important to have that
742             // animation be smooth.
743             mShownAlpha = mAlpha;
744             if (!mService.mLimitedAlphaCompositing
745                     || (!PixelFormat.formatHasAlpha(mWin.mAttrs.format)
746                     || (mWin.isIdentityMatrix(mDsDx, mDtDx, mDtDy, mDsDy)))) {
747                 //Slog.i(TAG_WM, "Applying alpha transform");
748                 if (screenAnimation) {
749                     mShownAlpha *= screenRotationAnimation.getEnterTransformation().getAlpha();
750                 }
751             } else {
752                 //Slog.i(TAG_WM, "Not applying alpha transform");
753             }
754 
755             if ((DEBUG_ANIM || WindowManagerService.localLOGV)
756                     && (mShownAlpha == 1.0 || mShownAlpha == 0.0)) Slog.v(
757                     TAG, "computeShownFrameLocked: Animating " + this + " mAlpha=" + mAlpha
758                     + " screen=" + (screenAnimation ?
759                             screenRotationAnimation.getEnterTransformation().getAlpha() : "null"));
760             return;
761         } else if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
762             return;
763         } else if (mWin.isDragResizeChanged()) {
764             // This window is awaiting a relayout because user just started (or ended)
765             // drag-resizing. The shown frame (which affects surface size and pos)
766             // should not be updated until we get next finished draw with the new surface.
767             // Otherwise one or two frames rendered with old settings would be displayed
768             // with new geometry.
769             return;
770         }
771 
772         if (WindowManagerService.localLOGV) Slog.v(
773                 TAG, "computeShownFrameLocked: " + this +
774                 " not attached, mAlpha=" + mAlpha);
775 
776         mShownAlpha = mAlpha;
777         mHaveMatrix = false;
778         mDsDx = mWin.mGlobalScale;
779         mDtDx = 0;
780         mDtDy = 0;
781         mDsDy = mWin.mGlobalScale;
782     }
783 
784     /**
785      * Calculate the window-space crop rect and fill clipRect.
786      * @return true if clipRect has been filled otherwise, no window space crop should be applied.
787      */
calculateCrop(Rect clipRect)788     private boolean calculateCrop(Rect clipRect) {
789         final WindowState w = mWin;
790         final DisplayContent displayContent = w.getDisplayContent();
791         clipRect.setEmpty();
792 
793         if (displayContent == null) {
794             return false;
795         }
796 
797         if (w.inPinnedWindowingMode()) {
798             return false;
799         }
800 
801         // If we're animating, the wallpaper should only
802         // be updated at the end of the animation.
803         if (w.mAttrs.type == TYPE_WALLPAPER) {
804             return false;
805         }
806 
807         if (DEBUG_WINDOW_CROP) Slog.d(TAG,
808                 "Updating crop win=" + w + " mLastCrop=" + mLastClipRect);
809 
810         w.calculatePolicyCrop(mSystemDecorRect);
811 
812         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "Applying decor to crop win=" + w + " mDecorFrame="
813                 + w.mDecorFrame + " mSystemDecorRect=" + mSystemDecorRect);
814 
815         final Task task = w.getTask();
816         final boolean fullscreen = w.fillsDisplay() || (task != null && task.isFullscreen());
817         final boolean isFreeformResizing =
818                 w.isDragResizing() && w.getResizeMode() == DRAG_RESIZE_MODE_FREEFORM;
819 
820         // We use the clip rect as provided by the tranformation for non-fullscreen windows to
821         // avoid premature clipping with the system decor rect.
822         clipRect.set(mSystemDecorRect);
823         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "win=" + w + " Initial clip rect: " + clipRect
824                 + " fullscreen=" + fullscreen);
825 
826         w.expandForSurfaceInsets(clipRect);
827 
828         // The clip rect was generated assuming (0,0) as the window origin,
829         // so we need to translate to match the actual surface coordinates.
830         clipRect.offset(w.mAttrs.surfaceInsets.left, w.mAttrs.surfaceInsets.top);
831 
832         if (DEBUG_WINDOW_CROP) Slog.d(TAG,
833                 "win=" + w + " Clip rect after stack adjustment=" + clipRect);
834 
835         w.transformClipRectFromScreenToSurfaceSpace(clipRect);
836 
837         return true;
838     }
839 
applyCrop(Rect clipRect, boolean recoveringMemory)840     private void applyCrop(Rect clipRect, boolean recoveringMemory) {
841         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "applyCrop: win=" + mWin
842                 + " clipRect=" + clipRect);
843         if (clipRect != null) {
844             if (!clipRect.equals(mLastClipRect)) {
845                 mLastClipRect.set(clipRect);
846                 mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
847             }
848         } else {
849             mSurfaceController.clearCropInTransaction(recoveringMemory);
850         }
851     }
852 
setSurfaceBoundariesLocked(final boolean recoveringMemory)853     void setSurfaceBoundariesLocked(final boolean recoveringMemory) {
854         if (mSurfaceController == null) {
855             return;
856         }
857 
858         final WindowState w = mWin;
859         final LayoutParams attrs = mWin.getAttrs();
860         final Task task = w.getTask();
861 
862         mTmpSize.set(0, 0, 0, 0);
863         calculateSurfaceBounds(w, attrs);
864 
865         mExtraHScale = (float) 1.0;
866         mExtraVScale = (float) 1.0;
867 
868         boolean wasForceScaled = mForceScaleUntilResize;
869         boolean wasSeamlesslyRotated = w.mSeamlesslyRotated;
870 
871         // Once relayout has been called at least once, we need to make sure
872         // we only resize the client surface during calls to relayout. For
873         // clients which use indeterminate measure specs (MATCH_PARENT),
874         // we may try and change their window size without a call to relayout.
875         // However, this would be unsafe, as the client may be in the middle
876         // of producing a frame at the old size, having just completed layout
877         // to find the surface size changed underneath it.
878         final boolean relayout = !w.mRelayoutCalled || w.mInRelayout;
879         if (relayout) {
880             mSurfaceResized = mSurfaceController.setSizeInTransaction(
881                     mTmpSize.width(), mTmpSize.height(), recoveringMemory);
882         } else {
883             mSurfaceResized = false;
884         }
885         mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
886         // If we are undergoing seamless rotation, the surface has already
887         // been set up to persist at it's old location. We need to freeze
888         // updates until a resize occurs.
889         mService.markForSeamlessRotation(w, w.mSeamlesslyRotated && !mSurfaceResized);
890 
891         Rect clipRect = null;
892         if (calculateCrop(mTmpClipRect)) {
893             clipRect = mTmpClipRect;
894         }
895 
896         float surfaceWidth = mSurfaceController.getWidth();
897         float surfaceHeight = mSurfaceController.getHeight();
898 
899         final Rect insets = attrs.surfaceInsets;
900 
901         if (isForceScaled()) {
902             int hInsets = insets.left + insets.right;
903             int vInsets = insets.top + insets.bottom;
904             float surfaceContentWidth = surfaceWidth - hInsets;
905             float surfaceContentHeight = surfaceHeight - vInsets;
906             if (!mForceScaleUntilResize) {
907                 mSurfaceController.forceScaleableInTransaction(true);
908             }
909 
910             int posX = 0;
911             int posY = 0;
912             task.mStack.getDimBounds(mTmpStackBounds);
913 
914             boolean allowStretching = false;
915             task.mStack.getFinalAnimationSourceHintBounds(mTmpSourceBounds);
916             // If we don't have source bounds, we can attempt to use the content insets
917             // in the following scenario:
918             //    1. We have content insets.
919             //    2. We are not transitioning to full screen
920             // We have to be careful to check "lastAnimatingBoundsWasToFullscreen" rather than
921             // the mBoundsAnimating state, as we may have already left it and only be here
922             // because of the force-scale until resize state.
923             if (mTmpSourceBounds.isEmpty() && (mWin.mLastRelayoutContentInsets.width() > 0
924                     || mWin.mLastRelayoutContentInsets.height() > 0)
925                         && !task.mStack.lastAnimatingBoundsWasToFullscreen()) {
926                 mTmpSourceBounds.set(task.mStack.mPreAnimationBounds);
927                 mTmpSourceBounds.inset(mWin.mLastRelayoutContentInsets);
928                 allowStretching = true;
929             }
930 
931             // Make sure that what we're animating to and from is actually the right size in case
932             // the window cannot take up the full screen.
933             mTmpStackBounds.intersectUnchecked(w.mParentFrame);
934             mTmpSourceBounds.intersectUnchecked(w.mParentFrame);
935             mTmpAnimatingBounds.intersectUnchecked(w.mParentFrame);
936 
937             if (!mTmpSourceBounds.isEmpty()) {
938                 // Get the final target stack bounds, if we are not animating, this is just the
939                 // current stack bounds
940                 task.mStack.getFinalAnimationBounds(mTmpAnimatingBounds);
941 
942                 // Calculate the current progress and interpolate the difference between the target
943                 // and source bounds
944                 float finalWidth = mTmpAnimatingBounds.width();
945                 float initialWidth = mTmpSourceBounds.width();
946                 float tw = (surfaceContentWidth - mTmpStackBounds.width())
947                         / (surfaceContentWidth - mTmpAnimatingBounds.width());
948                 float th = tw;
949                 mExtraHScale = (initialWidth + tw * (finalWidth - initialWidth)) / initialWidth;
950                 if (allowStretching) {
951                     float finalHeight = mTmpAnimatingBounds.height();
952                     float initialHeight = mTmpSourceBounds.height();
953                     th = (surfaceContentHeight - mTmpStackBounds.height())
954                         / (surfaceContentHeight - mTmpAnimatingBounds.height());
955                     mExtraVScale = (initialHeight + tw * (finalHeight - initialHeight))
956                             / initialHeight;
957                 } else {
958                     mExtraVScale = mExtraHScale;
959                 }
960 
961                 // Adjust the position to account for the inset bounds
962                 posX -= (int) (tw * mExtraHScale * mTmpSourceBounds.left);
963                 posY -= (int) (th * mExtraVScale * mTmpSourceBounds.top);
964 
965                 // In pinned mode the clip rectangle applied to us by our stack has been
966                 // expanded outwards to allow for shadows. However in case of source bounds set
967                 // we need to crop to within the surface. The code above has scaled and positioned
968                 // the surface to fit the unexpanded stack bounds, but now we need to reapply
969                 // the cropping that the stack would have applied if it weren't expanded. This
970                 // can be different in each direction based on the source bounds.
971                 clipRect = mTmpClipRect;
972                 clipRect.set((int)((insets.left + mTmpSourceBounds.left) * tw),
973                         (int)((insets.top + mTmpSourceBounds.top) * th),
974                         insets.left + (int)(surfaceWidth
975                                 - (tw* (surfaceWidth - mTmpSourceBounds.right))),
976                         insets.top + (int)(surfaceHeight
977                                 - (th * (surfaceHeight - mTmpSourceBounds.bottom))));
978             } else {
979                 // We want to calculate the scaling based on the content area, not based on
980                 // the entire surface, so that we scale in sync with windows that don't have insets.
981                 mExtraHScale = mTmpStackBounds.width() / surfaceContentWidth;
982                 mExtraVScale = mTmpStackBounds.height() / surfaceContentHeight;
983 
984                 // Since we are scaled to fit in our previously desired crop, we can now
985                 // expose the whole window in buffer space, and not risk extending
986                 // past where the system would have cropped us
987                 clipRect = null;
988             }
989 
990             // In the case of ForceScaleToStack we scale entire tasks together,
991             // and so we need to scale our offsets relative to the task bounds
992             // or parent and child windows would fall out of alignment.
993             posX -= (int) (attrs.x * (1 - mExtraHScale));
994             posY -= (int) (attrs.y * (1 - mExtraVScale));
995 
996             // Imagine we are scaling down. As we scale the buffer down, we decrease the
997             // distance between the surface top left, and the start of the surface contents
998             // (previously it was surfaceInsets.left pixels in screen space but now it
999             // will be surfaceInsets.left*mExtraHScale). This means in order to keep the
1000             // non inset content at the same position, we have to shift the whole window
1001             // forward. Likewise for scaling up, we've increased this distance, and we need
1002             // to shift by a negative number to compensate.
1003             posX += insets.left * (1 - mExtraHScale);
1004             posY += insets.top * (1 - mExtraVScale);
1005 
1006             mSurfaceController.setPositionInTransaction((float) Math.floor(posX),
1007                     (float) Math.floor(posY), recoveringMemory);
1008 
1009             // Various surfaces in the scaled stack may resize at different times.
1010             // We need to ensure for each surface, that we disable transformation matrix
1011             // scaling in the same transaction which we resize the surface in.
1012             // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
1013             // then take over the scaling until the new buffer arrives, and things
1014             // will be seamless.
1015             if (mPipAnimationStarted == false) {
1016                 mForceScaleUntilResize = true;
1017                 mPipAnimationStarted = true;
1018             }
1019         } else {
1020             mPipAnimationStarted = false;
1021 
1022             if (!w.mSeamlesslyRotated) {
1023                 // Used to offset the WSA when stack position changes before a resize.
1024                 int xOffset = mXOffset;
1025                 int yOffset = mYOffset;
1026                 if (mOffsetPositionForStackResize) {
1027                     if (relayout) {
1028                         // Once a relayout is called, reset the offset back to 0 and defer
1029                         // setting it until a new frame with the updated size. This ensures that
1030                         // the WS position is reset (so the stack position is shown) at the same
1031                         // time that the buffer size changes.
1032                         setOffsetPositionForStackResize(false);
1033                         mSurfaceController.deferTransactionUntil(mSurfaceController.getHandle(),
1034                                 mWin.getFrameNumber());
1035                     } else {
1036                         final TaskStack stack = mWin.getStack();
1037                         mTmpPos.x = 0;
1038                         mTmpPos.y = 0;
1039                         if (stack != null) {
1040                             stack.getRelativePosition(mTmpPos);
1041                         }
1042 
1043                         xOffset = -mTmpPos.x;
1044                         yOffset = -mTmpPos.y;
1045 
1046                         // Crop also needs to be extended so the bottom isn't cut off when the WSA
1047                         // position is moved.
1048                         if (clipRect != null) {
1049                             clipRect.right += mTmpPos.x;
1050                             clipRect.bottom += mTmpPos.y;
1051                         }
1052                     }
1053                 }
1054                 mSurfaceController.setPositionInTransaction(xOffset, yOffset, recoveringMemory);
1055             }
1056         }
1057 
1058         // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
1059         // to prevent further updates until buffer latch.
1060         // When ending both force scaling, and seamless rotation, we need to freeze
1061         // the Surface geometry until a buffer comes in at the new size (normally position and crop
1062         // are unfrozen). setGeometryAppliesWithResizeInTransaction accomplishes this for us.
1063         if ((wasForceScaled && !mForceScaleUntilResize) ||
1064                 (wasSeamlesslyRotated && !w.mSeamlesslyRotated)) {
1065             mSurfaceController.setGeometryAppliesWithResizeInTransaction(true);
1066             mSurfaceController.forceScaleableInTransaction(false);
1067         }
1068 
1069         if (!w.mSeamlesslyRotated) {
1070             applyCrop(clipRect, recoveringMemory);
1071             mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
1072                     mDtDx * w.mVScale * mExtraVScale,
1073                     mDtDy * w.mHScale * mExtraHScale,
1074                     mDsDy * w.mVScale * mExtraVScale, recoveringMemory);
1075         }
1076 
1077         if (mSurfaceResized) {
1078             mReportSurfaceResized = true;
1079             mAnimator.setPendingLayoutChanges(w.getDisplayId(),
1080                     FINISH_LAYOUT_REDO_WALLPAPER);
1081         }
1082     }
1083 
1084     /**
1085      * Get rect of the task this window is currently in. If there is no task, rect will be set to
1086      * empty.
1087      */
getContainerRect(Rect rect)1088     void getContainerRect(Rect rect) {
1089         final Task task = mWin.getTask();
1090         if (task != null) {
1091             task.getDimBounds(rect);
1092         } else {
1093             rect.left = rect.top = rect.right = rect.bottom = 0;
1094         }
1095     }
1096 
prepareSurfaceLocked(final boolean recoveringMemory)1097     void prepareSurfaceLocked(final boolean recoveringMemory) {
1098         final WindowState w = mWin;
1099         if (!hasSurface()) {
1100 
1101             // There is no need to wait for an animation change if our window is gone for layout
1102             // already as we'll never be visible.
1103             if (w.getOrientationChanging() && w.isGoneForLayoutLw()) {
1104                 if (DEBUG_ORIENTATION) {
1105                     Slog.v(TAG, "Orientation change skips hidden " + w);
1106                 }
1107                 w.setOrientationChanging(false);
1108             }
1109             return;
1110         }
1111 
1112         boolean displayed = false;
1113 
1114         computeShownFrameLocked();
1115 
1116         setSurfaceBoundariesLocked(recoveringMemory);
1117 
1118         if (mIsWallpaper && !mWin.mWallpaperVisible) {
1119             // Wallpaper is no longer visible and there is no wp target => hide it.
1120             hide("prepareSurfaceLocked");
1121         } else if (w.isParentWindowHidden() || !w.isOnScreen()) {
1122             hide("prepareSurfaceLocked");
1123             mWallpaperControllerLocked.hideWallpapers(w);
1124 
1125             // If we are waiting for this window to handle an orientation change. If this window is
1126             // really hidden (gone for layout), there is no point in still waiting for it.
1127             // Note that this does introduce a potential glitch if the window becomes unhidden
1128             // before it has drawn for the new orientation.
1129             if (w.getOrientationChanging() && w.isGoneForLayoutLw()) {
1130                 w.setOrientationChanging(false);
1131                 if (DEBUG_ORIENTATION) Slog.v(TAG,
1132                         "Orientation change skips hidden " + w);
1133             }
1134         } else if (mLastLayer != mAnimLayer
1135                 || mLastAlpha != mShownAlpha
1136                 || mLastDsDx != mDsDx
1137                 || mLastDtDx != mDtDx
1138                 || mLastDsDy != mDsDy
1139                 || mLastDtDy != mDtDy
1140                 || w.mLastHScale != w.mHScale
1141                 || w.mLastVScale != w.mVScale
1142                 || mLastHidden) {
1143             displayed = true;
1144             mLastAlpha = mShownAlpha;
1145             mLastLayer = mAnimLayer;
1146             mLastDsDx = mDsDx;
1147             mLastDtDx = mDtDx;
1148             mLastDsDy = mDsDy;
1149             mLastDtDy = mDtDy;
1150             w.mLastHScale = w.mHScale;
1151             w.mLastVScale = w.mVScale;
1152             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(w,
1153                     "controller=" + mSurfaceController +
1154                     "alpha=" + mShownAlpha + " layer=" + mAnimLayer
1155                     + " matrix=[" + mDsDx + "*" + w.mHScale
1156                     + "," + mDtDx + "*" + w.mVScale
1157                     + "][" + mDtDy + "*" + w.mHScale
1158                     + "," + mDsDy + "*" + w.mVScale + "]", false);
1159 
1160             boolean prepared =
1161                 mSurfaceController.prepareToShowInTransaction(mShownAlpha,
1162                         mDsDx * w.mHScale * mExtraHScale,
1163                         mDtDx * w.mVScale * mExtraVScale,
1164                         mDtDy * w.mHScale * mExtraHScale,
1165                         mDsDy * w.mVScale * mExtraVScale,
1166                         recoveringMemory);
1167 
1168             if (prepared && mDrawState == HAS_DRAWN) {
1169                 if (mLastHidden) {
1170                     if (showSurfaceRobustlyLocked()) {
1171                         markPreservedSurfaceForDestroy();
1172                         mAnimator.requestRemovalOfReplacedWindows(w);
1173                         mLastHidden = false;
1174                         if (mIsWallpaper) {
1175                             w.dispatchWallpaperVisibility(true);
1176                         }
1177                         // This draw means the difference between unique content and mirroring.
1178                         // Run another pass through performLayout to set mHasContent in the
1179                         // LogicalDisplay.
1180                         mAnimator.setPendingLayoutChanges(w.getDisplayId(),
1181                                 FINISH_LAYOUT_REDO_ANIM);
1182                     } else {
1183                         w.setOrientationChanging(false);
1184                     }
1185                 }
1186             }
1187             if (hasSurface()) {
1188                 w.mToken.hasVisible = true;
1189             }
1190         } else {
1191             if (DEBUG_ANIM && isAnimationSet()) {
1192                 Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
1193             }
1194             displayed = true;
1195         }
1196 
1197         if (w.getOrientationChanging()) {
1198             if (!w.isDrawnLw()) {
1199                 mAnimator.mBulkUpdateParams &= ~SET_ORIENTATION_CHANGE_COMPLETE;
1200                 mAnimator.mLastWindowFreezeSource = w;
1201                 if (DEBUG_ORIENTATION) Slog.v(TAG,
1202                         "Orientation continue waiting for draw in " + w);
1203             } else {
1204                 w.setOrientationChanging(false);
1205                 if (DEBUG_ORIENTATION) Slog.v(TAG, "Orientation change complete in " + w);
1206             }
1207         }
1208 
1209         if (displayed) {
1210             w.mToken.hasVisible = true;
1211         }
1212     }
1213 
setTransparentRegionHintLocked(final Region region)1214     void setTransparentRegionHintLocked(final Region region) {
1215         if (mSurfaceController == null) {
1216             Slog.w(TAG, "setTransparentRegionHint: null mSurface after mHasSurface true");
1217             return;
1218         }
1219         mSurfaceController.setTransparentRegionHint(region);
1220     }
1221 
setWallpaperOffset(int dx, int dy)1222     boolean setWallpaperOffset(int dx, int dy) {
1223         if (mXOffset == dx && mYOffset == dy) {
1224             return false;
1225         }
1226         mXOffset = dx;
1227         mYOffset = dy;
1228 
1229         try {
1230             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG, ">>> OPEN TRANSACTION setWallpaperOffset");
1231             mService.openSurfaceTransaction();
1232             mSurfaceController.setPositionInTransaction(dx, dy, false);
1233             applyCrop(null, false);
1234         } catch (RuntimeException e) {
1235             Slog.w(TAG, "Error positioning surface of " + mWin
1236                     + " pos=(" + dx + "," + dy + ")", e);
1237         } finally {
1238             mService.closeSurfaceTransaction("setWallpaperOffset");
1239             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
1240                     "<<< CLOSE TRANSACTION setWallpaperOffset");
1241             return true;
1242         }
1243     }
1244 
1245     /**
1246      * Try to change the pixel format without recreating the surface. This
1247      * will be common in the case of changing from PixelFormat.OPAQUE to
1248      * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
1249      * requested formats resolve to the same underlying SurfaceControl format
1250      * @return True if format was succesfully changed, false otherwise
1251      */
tryChangeFormatInPlaceLocked()1252     boolean tryChangeFormatInPlaceLocked() {
1253         if (mSurfaceController == null) {
1254             return false;
1255         }
1256         final LayoutParams attrs = mWin.getAttrs();
1257         final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
1258         final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
1259         if (format == mSurfaceFormat) {
1260             setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
1261             return true;
1262         }
1263         return false;
1264     }
1265 
setOpaqueLocked(boolean isOpaque)1266     void setOpaqueLocked(boolean isOpaque) {
1267         if (mSurfaceController == null) {
1268             return;
1269         }
1270         mSurfaceController.setOpaque(isOpaque);
1271     }
1272 
setSecureLocked(boolean isSecure)1273     void setSecureLocked(boolean isSecure) {
1274         if (mSurfaceController == null) {
1275             return;
1276         }
1277         mSurfaceController.setSecure(isSecure);
1278     }
1279 
1280     /**
1281      * Have the surface flinger show a surface, robustly dealing with
1282      * error conditions.  In particular, if there is not enough memory
1283      * to show the surface, then we will try to get rid of other surfaces
1284      * in order to succeed.
1285      *
1286      * @return Returns true if the surface was successfully shown.
1287      */
showSurfaceRobustlyLocked()1288     private boolean showSurfaceRobustlyLocked() {
1289         if (mWin.getWindowConfiguration().windowsAreScaleable()) {
1290             mSurfaceController.forceScaleableInTransaction(true);
1291         }
1292 
1293         boolean shown = mSurfaceController.showRobustlyInTransaction();
1294         if (!shown)
1295             return false;
1296 
1297         // If we had a preserved surface it's no longer needed, and it may be harmful
1298         // if we are transparent.
1299         if (mPendingDestroySurface != null && mDestroyPreservedSurfaceUponRedraw) {
1300             mPendingDestroySurface.mSurfaceControl.hide();
1301             mPendingDestroySurface.reparentChildrenInTransaction(mSurfaceController);
1302         }
1303 
1304         return true;
1305     }
1306 
applyEnterAnimationLocked()1307     void applyEnterAnimationLocked() {
1308         // If we are the new part of a window replacement transition and we have requested
1309         // not to animate, we instead want to make it seamless, so we don't want to apply
1310         // an enter transition.
1311         if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
1312             return;
1313         }
1314         final int transit;
1315         if (mEnterAnimationPending) {
1316             mEnterAnimationPending = false;
1317             transit = WindowManagerPolicy.TRANSIT_ENTER;
1318         } else {
1319             transit = WindowManagerPolicy.TRANSIT_SHOW;
1320         }
1321         applyAnimationLocked(transit, true);
1322         //TODO (multidisplay): Magnification is supported only for the default display.
1323         if (mService.mAccessibilityController != null
1324                 && mWin.getDisplayId() == DEFAULT_DISPLAY) {
1325             mService.mAccessibilityController.onWindowTransitionLocked(mWin, transit);
1326         }
1327     }
1328 
1329     /**
1330      * Choose the correct animation and set it to the passed WindowState.
1331      * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn
1332      *      then the animation will be app_starting_exit. Any other value loads the animation from
1333      *      the switch statement below.
1334      * @param isEntrance The animation type the last time this was called. Used to keep from
1335      *      loading the same animation twice.
1336      * @return true if an animation has been loaded.
1337      */
applyAnimationLocked(int transit, boolean isEntrance)1338     boolean applyAnimationLocked(int transit, boolean isEntrance) {
1339         if (mWin.isSelfAnimating() && mAnimationIsEntrance == isEntrance) {
1340             // If we are trying to apply an animation, but already running
1341             // an animation of the same type, then just leave that one alone.
1342             return true;
1343         }
1344 
1345         if (isEntrance && mWin.mAttrs.type == TYPE_INPUT_METHOD) {
1346             mWin.getDisplayContent().adjustForImeIfNeeded();
1347             mWin.setDisplayLayoutNeeded();
1348             mService.mWindowPlacerLocked.requestTraversal();
1349         }
1350 
1351         // Only apply an animation if the display isn't frozen.  If it is
1352         // frozen, there is no reason to animate and it can cause strange
1353         // artifacts when we unfreeze the display if some different animation
1354         // is running.
1355         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#applyAnimationLocked");
1356         if (mWin.mToken.okToAnimate()) {
1357             int anim = mPolicy.selectAnimationLw(mWin, transit);
1358             int attr = -1;
1359             Animation a = null;
1360             if (anim != 0) {
1361                 a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
1362             } else {
1363                 switch (transit) {
1364                     case WindowManagerPolicy.TRANSIT_ENTER:
1365                         attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
1366                         break;
1367                     case WindowManagerPolicy.TRANSIT_EXIT:
1368                         attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
1369                         break;
1370                     case WindowManagerPolicy.TRANSIT_SHOW:
1371                         attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
1372                         break;
1373                     case WindowManagerPolicy.TRANSIT_HIDE:
1374                         attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
1375                         break;
1376                 }
1377                 if (attr >= 0) {
1378                     a = mService.mAppTransition.loadAnimationAttr(mWin.mAttrs, attr, TRANSIT_NONE);
1379                 }
1380             }
1381             if (DEBUG_ANIM) Slog.v(TAG,
1382                     "applyAnimation: win=" + this
1383                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
1384                     + " a=" + a
1385                     + " transit=" + transit
1386                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
1387             if (a != null) {
1388                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
1389                 mWin.startAnimation(a);
1390                 mAnimationIsEntrance = isEntrance;
1391             }
1392         } else {
1393             mWin.cancelAnimation();
1394         }
1395 
1396         if (!isEntrance && mWin.mAttrs.type == TYPE_INPUT_METHOD) {
1397             mWin.getDisplayContent().adjustForImeIfNeeded();
1398         }
1399 
1400         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
1401         return isAnimationSet();
1402     }
1403 
writeToProto(ProtoOutputStream proto, long fieldId)1404     void writeToProto(ProtoOutputStream proto, long fieldId) {
1405         final long token = proto.start(fieldId);
1406         mLastClipRect.writeToProto(proto, LAST_CLIP_RECT);
1407         if (mSurfaceController != null) {
1408             mSurfaceController.writeToProto(proto, SURFACE);
1409         }
1410         proto.write(DRAW_STATE, mDrawState);
1411         mSystemDecorRect.writeToProto(proto, SYSTEM_DECOR_RECT);
1412         proto.end(token);
1413     }
1414 
dump(PrintWriter pw, String prefix, boolean dumpAll)1415     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1416         if (mAnimationIsEntrance) {
1417             pw.print(prefix); pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
1418         }
1419         if (mSurfaceController != null) {
1420             mSurfaceController.dump(pw, prefix, dumpAll);
1421         }
1422         if (dumpAll) {
1423             pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString());
1424             pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden);
1425             pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
1426             pw.print(" mLastClipRect="); mLastClipRect.printShortString(pw);
1427 
1428             if (!mLastFinalClipRect.isEmpty()) {
1429                 pw.print(" mLastFinalClipRect="); mLastFinalClipRect.printShortString(pw);
1430             }
1431             pw.println();
1432         }
1433 
1434         if (mPendingDestroySurface != null) {
1435             pw.print(prefix); pw.print("mPendingDestroySurface=");
1436                     pw.println(mPendingDestroySurface);
1437         }
1438         if (mSurfaceResized || mSurfaceDestroyDeferred) {
1439             pw.print(prefix); pw.print("mSurfaceResized="); pw.print(mSurfaceResized);
1440                     pw.print(" mSurfaceDestroyDeferred="); pw.println(mSurfaceDestroyDeferred);
1441         }
1442         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
1443             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
1444                     pw.print(" mAlpha="); pw.print(mAlpha);
1445                     pw.print(" mLastAlpha="); pw.println(mLastAlpha);
1446         }
1447         if (mHaveMatrix || mWin.mGlobalScale != 1) {
1448             pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
1449                     pw.print(" mDsDx="); pw.print(mDsDx);
1450                     pw.print(" mDtDx="); pw.print(mDtDx);
1451                     pw.print(" mDtDy="); pw.print(mDtDy);
1452                     pw.print(" mDsDy="); pw.println(mDsDy);
1453         }
1454         if (mAnimationStartDelayed) {
1455             pw.print(prefix); pw.print("mAnimationStartDelayed="); pw.print(mAnimationStartDelayed);
1456         }
1457     }
1458 
1459     @Override
toString()1460     public String toString() {
1461         StringBuffer sb = new StringBuffer("WindowStateAnimator{");
1462         sb.append(Integer.toHexString(System.identityHashCode(this)));
1463         sb.append(' ');
1464         sb.append(mWin.mAttrs.getTitle());
1465         sb.append('}');
1466         return sb.toString();
1467     }
1468 
reclaimSomeSurfaceMemory(String operation, boolean secure)1469     void reclaimSomeSurfaceMemory(String operation, boolean secure) {
1470         mService.mRoot.reclaimSomeSurfaceMemory(this, operation, secure);
1471     }
1472 
getShown()1473     boolean getShown() {
1474         if (mSurfaceController != null) {
1475             return mSurfaceController.getShown();
1476         }
1477         return false;
1478     }
1479 
destroySurface()1480     void destroySurface() {
1481         try {
1482             if (mSurfaceController != null) {
1483                 mSurfaceController.destroyNotInTransaction();
1484             }
1485         } catch (RuntimeException e) {
1486             Slog.w(TAG, "Exception thrown when destroying surface " + this
1487                     + " surface " + mSurfaceController + " session " + mSession + ": " + e);
1488         } finally {
1489             mWin.setHasSurface(false);
1490             mSurfaceController = null;
1491             mDrawState = NO_SURFACE;
1492         }
1493     }
1494 
seamlesslyRotateWindow(SurfaceControl.Transaction t, int oldRotation, int newRotation)1495     void seamlesslyRotateWindow(SurfaceControl.Transaction t,
1496             int oldRotation, int newRotation) {
1497         final WindowState w = mWin;
1498         if (!w.isVisibleNow() || w.mIsWallpaper) {
1499             return;
1500         }
1501 
1502         final Rect cropRect = mService.mTmpRect;
1503         final Rect displayRect = mService.mTmpRect2;
1504         final RectF frameRect = mService.mTmpRectF;
1505         final Matrix transform = mService.mTmpTransform;
1506 
1507         final float x = w.mFrame.left;
1508         final float y = w.mFrame.top;
1509         final float width = w.mFrame.width();
1510         final float height = w.mFrame.height();
1511 
1512         mService.getDefaultDisplayContentLocked().getBounds(displayRect);
1513         final float displayWidth = displayRect.width();
1514         final float displayHeight = displayRect.height();
1515 
1516         // Compute a transform matrix to undo the coordinate space transformation,
1517         // and present the window at the same physical position it previously occupied.
1518         final int deltaRotation = DisplayContent.deltaRotation(newRotation, oldRotation);
1519         DisplayContent.createRotationMatrix(deltaRotation, x, y, displayWidth, displayHeight,
1520                 transform);
1521 
1522         // We just need to apply a rotation matrix to the window. For example
1523         // if we have a portrait window and rotate to landscape, the window is still portrait
1524         // and now extends off the bottom of the screen (and only halfway across). Essentially we
1525         // apply a transform to display the current buffer at it's old position
1526         // (in the new coordinate space). We then freeze layer updates until the resize
1527         // occurs, at which point we undo, them.
1528         mService.markForSeamlessRotation(w, true);
1529         transform.getValues(mService.mTmpFloats);
1530 
1531         float DsDx = mService.mTmpFloats[Matrix.MSCALE_X];
1532         float DtDx = mService.mTmpFloats[Matrix.MSKEW_Y];
1533         float DtDy = mService.mTmpFloats[Matrix.MSKEW_X];
1534         float DsDy = mService.mTmpFloats[Matrix.MSCALE_Y];
1535         float nx = mService.mTmpFloats[Matrix.MTRANS_X];
1536         float ny = mService.mTmpFloats[Matrix.MTRANS_Y];
1537         mSurfaceController.setPosition(t, nx, ny, false);
1538         mSurfaceController.setMatrix(t, DsDx * w.mHScale, DtDx * w.mVScale, DtDy
1539                 * w.mHScale, DsDy * w.mVScale, false);
1540     }
1541 
1542     /** The force-scaled state for a given window can persist past
1543      * the state for it's stack as the windows complete resizing
1544      * independently of one another.
1545      */
isForceScaled()1546     boolean isForceScaled() {
1547         final Task task = mWin.getTask();
1548         if (task != null && task.mStack.isForceScaled()) {
1549             return true;
1550         }
1551         return mForceScaleUntilResize;
1552     }
1553 
detachChildren()1554     void detachChildren() {
1555         if (mSurfaceController != null) {
1556             mSurfaceController.detachChildren();
1557         }
1558         mChildrenDetached = true;
1559     }
1560 
getLayer()1561     int getLayer() {
1562         return mLastLayer;
1563     }
1564 
setOffsetPositionForStackResize(boolean offsetPositionForStackResize)1565     void setOffsetPositionForStackResize(boolean offsetPositionForStackResize) {
1566         mOffsetPositionForStackResize = offsetPositionForStackResize;
1567     }
1568 }
1569