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