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