1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.view.WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
20 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY;
21 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
22 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
23 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
24 import static android.view.WindowManager.TRANSIT_OLD_NONE;
25 
26 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_DRAW;
27 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
28 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STARTING_WINDOW;
29 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
30 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
31 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
32 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
33 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
34 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
35 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
37 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
38 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
39 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STARTING_WINDOW_VERBOSE;
40 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_VISIBILITY;
41 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
42 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
43 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
44 import static com.android.server.wm.WindowManagerService.logWithStack;
45 import static com.android.server.wm.WindowStateAnimatorProto.DRAW_STATE;
46 import static com.android.server.wm.WindowStateAnimatorProto.SURFACE;
47 import static com.android.server.wm.WindowStateAnimatorProto.SYSTEM_DECOR_RECT;
48 
49 import android.content.Context;
50 import android.graphics.PixelFormat;
51 import android.graphics.Rect;
52 import android.os.Debug;
53 import android.os.Trace;
54 import android.util.Slog;
55 import android.util.proto.ProtoOutputStream;
56 import android.view.Surface.OutOfResourcesException;
57 import android.view.SurfaceControl;
58 import android.view.WindowManager;
59 import android.view.WindowManager.LayoutParams;
60 import android.view.animation.Animation;
61 import android.view.animation.AnimationUtils;
62 
63 import com.android.internal.protolog.common.ProtoLog;
64 import com.android.server.policy.WindowManagerPolicy;
65 
66 import java.io.PrintWriter;
67 
68 /**
69  * Keep track of animations and surface operations for a single WindowState.
70  **/
71 class WindowStateAnimator {
72     static final String TAG = TAG_WITH_CLASS_NAME ? "WindowStateAnimator" : TAG_WM;
73     static final int PRESERVED_SURFACE_LAYER = 1;
74 
75     /**
76      * Mode how the window gets clipped by the root task bounds during an animation: The clipping
77      * should be applied after applying the animation transformation, i.e. the root task bounds
78      * don't move during the animation.
79      */
80     static final int ROOT_TASK_CLIP_AFTER_ANIM = 0;
81 
82     /**
83      * Mode how window gets clipped by the root task bounds during an animation: Don't clip the
84      * window by the root task bounds.
85      */
86     static final int ROOT_TASK_CLIP_NONE = 1;
87 
88     // Unchanging local convenience fields.
89     final WindowManagerService mService;
90     final WindowState mWin;
91     final WindowAnimator mAnimator;
92     final Session mSession;
93     final WindowManagerPolicy mPolicy;
94     final Context mContext;
95     final boolean mIsWallpaper;
96     private final WallpaperController mWallpaperControllerLocked;
97 
98     boolean mAnimationIsEntrance;
99 
100     WindowSurfaceController mSurfaceController;
101 
102     float mShownAlpha = 0;
103     float mAlpha = 0;
104     float mLastAlpha = 0;
105 
106     /**
107      * This is rectangle of the window's surface that is not covered by
108      * system decorations.
109      */
110     private final Rect mSystemDecorRect = new Rect();
111 
112     // Set to true if, when the window gets displayed, it should perform
113     // an enter animation.
114     boolean mEnterAnimationPending;
115 
116     /** Used to indicate that this window is undergoing an enter animation. Used for system
117      * windows to make the callback to View.dispatchOnWindowShownCallback(). Set when the
118      * window is first added or shown, cleared when the callback has been made. */
119     boolean mEnteringAnimation;
120 
121     /** The pixel format of the underlying SurfaceControl */
122     int mSurfaceFormat;
123 
124     /** This is set when there is no Surface */
125     static final int NO_SURFACE = 0;
126     /** This is set after the Surface has been created but before the window has been drawn. During
127      * this time the surface is hidden. */
128     static final int DRAW_PENDING = 1;
129     /** This is set after the window has finished drawing for the first time but before its surface
130      * is shown.  The surface will be displayed when the next layout is run. */
131     static final int COMMIT_DRAW_PENDING = 2;
132     /** This is set during the time after the window's drawing has been committed, and before its
133      * surface is actually shown.  It is used to delay showing the surface until all windows in a
134      * token are ready to be shown. */
135     static final int READY_TO_SHOW = 3;
136     /** Set when the window has been shown in the screen the first time. */
137     static final int HAS_DRAWN = 4;
138 
drawStateToString()139     String drawStateToString() {
140         switch (mDrawState) {
141             case NO_SURFACE: return "NO_SURFACE";
142             case DRAW_PENDING: return "DRAW_PENDING";
143             case COMMIT_DRAW_PENDING: return "COMMIT_DRAW_PENDING";
144             case READY_TO_SHOW: return "READY_TO_SHOW";
145             case HAS_DRAWN: return "HAS_DRAWN";
146             default: return Integer.toString(mDrawState);
147         }
148     }
149     int mDrawState;
150 
151     /** Was this window last hidden? */
152     boolean mLastHidden;
153 
154     int mAttrType;
155 
156     private final Rect mTmpSize = new Rect();
157 
158     /**
159      * Handles surface changes synchronized to after the client has drawn the surface. This
160      * transaction is currently used to reparent the old surface children to the new surface once
161      * the client has completed drawing to the new surface.
162      * This transaction is also used to merge transactions parceled in by the client. The client
163      * uses the transaction to update the relative z of its children from the old parent surface
164      * to the new parent surface once window manager reparents its children.
165      */
166     private final SurfaceControl.Transaction mPostDrawTransaction =
167             new SurfaceControl.Transaction();
168 
WindowStateAnimator(final WindowState win)169     WindowStateAnimator(final WindowState win) {
170         final WindowManagerService service = win.mWmService;
171 
172         mService = service;
173         mAnimator = service.mAnimator;
174         mPolicy = service.mPolicy;
175         mContext = service.mContext;
176 
177         mWin = win;
178         mSession = win.mSession;
179         mAttrType = win.mAttrs.type;
180         mIsWallpaper = win.mIsWallpaper;
181         mWallpaperControllerLocked = win.getDisplayContent().mWallpaperController;
182     }
183 
onAnimationFinished()184     void onAnimationFinished() {
185         // Done animating, clean up.
186         if (DEBUG_ANIM) Slog.v(
187                 TAG, "Animation done in " + this + ": exiting=" + mWin.mAnimatingExit
188                         + ", reportedVisible="
189                         + (mWin.mActivityRecord != null && mWin.mActivityRecord.reportedVisible));
190 
191         mWin.checkPolicyVisibilityChange();
192         final DisplayContent displayContent = mWin.getDisplayContent();
193         if ((mAttrType == LayoutParams.TYPE_STATUS_BAR
194                 || mAttrType == LayoutParams.TYPE_NOTIFICATION_SHADE) && mWin.isVisibleByPolicy()) {
195             // Upon completion of a not-visible to visible status bar animation a relayout is
196             // required.
197             displayContent.setLayoutNeeded();
198         }
199         mWin.onExitAnimationDone();
200         displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
201         if (displayContent.mWallpaperController.isWallpaperTarget(mWin)) {
202             displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
203         }
204         if (DEBUG_LAYOUT_REPEATS) {
205             mService.mWindowPlacerLocked.debugLayoutRepeats(
206                     "WindowStateAnimator", displayContent.pendingLayoutChanges);
207         }
208 
209         if (mWin.mActivityRecord != null) {
210             mWin.mActivityRecord.updateReportedVisibilityLocked();
211         }
212     }
213 
hide(SurfaceControl.Transaction transaction, String reason)214     void hide(SurfaceControl.Transaction transaction, String reason) {
215         if (!mLastHidden) {
216             //dump();
217             mLastHidden = true;
218 
219             if (mSurfaceController != null) {
220                 mSurfaceController.hide(transaction, reason);
221             }
222         }
223     }
224 
finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction, boolean forceApplyNow)225     boolean finishDrawingLocked(SurfaceControl.Transaction postDrawTransaction,
226             boolean forceApplyNow) {
227         final boolean startingWindow =
228                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
229         if (startingWindow) {
230             ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Finishing drawing window %s: mDrawState=%s",
231                     mWin, drawStateToString());
232         }
233 
234         boolean layoutNeeded = false;
235 
236         if (mDrawState == DRAW_PENDING) {
237             ProtoLog.v(WM_DEBUG_DRAW,
238                     "finishDrawingLocked: mDrawState=COMMIT_DRAW_PENDING %s in %s", mWin,
239                     mSurfaceController);
240             if (startingWindow) {
241                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "Draw state now committed in %s", mWin);
242             }
243             mDrawState = COMMIT_DRAW_PENDING;
244             layoutNeeded = true;
245         }
246 
247         if (postDrawTransaction != null) {
248             // If there is no surface, the last draw was for the previous surface. We don't want to
249             // wait until the new surface is shown and instead just apply the transaction right
250             // away.
251             if (mLastHidden && mDrawState != NO_SURFACE && !forceApplyNow) {
252                 mPostDrawTransaction.merge(postDrawTransaction);
253             } else {
254                 mWin.getSyncTransaction().merge(postDrawTransaction);
255             }
256             layoutNeeded = true;
257         }
258 
259         return layoutNeeded;
260     }
261 
262     // This must be called while inside a transaction.
commitFinishDrawingLocked()263     boolean commitFinishDrawingLocked() {
264         if (DEBUG_STARTING_WINDOW_VERBOSE &&
265                 mWin.mAttrs.type == WindowManager.LayoutParams.TYPE_APPLICATION_STARTING) {
266             Slog.i(TAG, "commitFinishDrawingLocked: " + mWin + " cur mDrawState="
267                     + drawStateToString());
268         }
269         if (mDrawState != COMMIT_DRAW_PENDING && mDrawState != READY_TO_SHOW) {
270             return false;
271         }
272         if (DEBUG_ANIM) {
273             Slog.i(TAG, "commitFinishDrawingLocked: mDrawState=READY_TO_SHOW " + mSurfaceController);
274         }
275         mDrawState = READY_TO_SHOW;
276         boolean result = false;
277         final ActivityRecord activity = mWin.mActivityRecord;
278         if (activity == null || activity.canShowWindows()
279                 || mWin.mAttrs.type == TYPE_APPLICATION_STARTING) {
280             result = mWin.performShowLocked();
281         }
282         return result;
283     }
284 
resetDrawState()285     void resetDrawState() {
286         mDrawState = DRAW_PENDING;
287 
288         if (mWin.mActivityRecord == null) {
289             return;
290         }
291 
292         if (!mWin.mActivityRecord.isAnimating(TRANSITION)) {
293             mWin.mActivityRecord.clearAllDrawn();
294         }
295     }
296 
createSurfaceLocked(int windowType)297     WindowSurfaceController createSurfaceLocked(int windowType) {
298         final WindowState w = mWin;
299 
300         if (mSurfaceController != null) {
301             return mSurfaceController;
302         }
303 
304         w.setHasSurface(false);
305 
306         if (DEBUG_ANIM) {
307             Slog.i(TAG, "createSurface " + this + ": mDrawState=DRAW_PENDING");
308         }
309 
310         resetDrawState();
311 
312         mService.makeWindowFreezingScreenIfNeededLocked(w);
313 
314         int flags = SurfaceControl.HIDDEN;
315         final WindowManager.LayoutParams attrs = w.mAttrs;
316 
317         if (w.isSecureLocked()) {
318             flags |= SurfaceControl.SECURE;
319         }
320 
321         if ((mWin.mAttrs.privateFlags & PRIVATE_FLAG_IS_ROUNDED_CORNERS_OVERLAY) != 0) {
322             flags |= SurfaceControl.SKIP_SCREENSHOT;
323         }
324 
325         w.calculateSurfaceBounds(attrs, mTmpSize);
326 
327         final int width = mTmpSize.width();
328         final int height = mTmpSize.height();
329 
330         if (DEBUG_VISIBILITY) {
331             Slog.v(TAG, "Creating surface in session "
332                     + mSession.mSurfaceSession + " window " + this
333                     + " w=" + width + " h=" + height
334                     + " x=" + mTmpSize.left + " y=" + mTmpSize.top
335                     + " format=" + attrs.format + " flags=" + flags);
336         }
337 
338         // Set up surface control with initial size.
339         try {
340 
341             // This can be removed once we move all Buffer Layers to use BLAST.
342             final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
343             final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
344 
345             mSurfaceController = new WindowSurfaceController(attrs.getTitle().toString(), width,
346                     height, format, flags, this, windowType);
347             mSurfaceController.setColorSpaceAgnostic((attrs.privateFlags
348                     & WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
349 
350             mSurfaceFormat = format;
351 
352             w.setHasSurface(true);
353             // The surface instance is changed. Make sure the input info can be applied to the
354             // new surface, e.g. relaunch activity.
355             w.mInputWindowHandle.forceChange();
356 
357             ProtoLog.i(WM_SHOW_SURFACE_ALLOC,
358                         "  CREATE SURFACE %s IN SESSION %s: pid=%d format=%d flags=0x%x / %s",
359                         mSurfaceController, mSession.mSurfaceSession, mSession.mPid, attrs.format,
360                         flags, this);
361         } catch (OutOfResourcesException e) {
362             Slog.w(TAG, "OutOfResourcesException creating surface");
363             mService.mRoot.reclaimSomeSurfaceMemory(this, "create", true);
364             mDrawState = NO_SURFACE;
365             return null;
366         } catch (Exception e) {
367             Slog.e(TAG, "Exception creating surface (parent dead?)", e);
368             mDrawState = NO_SURFACE;
369             return null;
370         }
371 
372         if (DEBUG) {
373             Slog.v(TAG, "Got surface: " + mSurfaceController
374                     + ", set left=" + w.getFrame().left + " top=" + w.getFrame().top);
375         }
376 
377         if (SHOW_LIGHT_TRANSACTIONS) {
378             Slog.i(TAG, ">>> OPEN TRANSACTION createSurfaceLocked");
379             WindowManagerService.logSurface(w, "CREATE pos=("
380                     + w.getFrame().left + "," + w.getFrame().top + ") ("
381                     + width + "x" + height + ")" + " HIDE", false);
382         }
383 
384         mLastHidden = true;
385 
386         if (DEBUG) Slog.v(TAG, "Created surface " + this);
387         return mSurfaceController;
388     }
389 
hasSurface()390     boolean hasSurface() {
391         return mSurfaceController != null && mSurfaceController.hasSurface();
392     }
393 
destroySurfaceLocked(SurfaceControl.Transaction t)394     void destroySurfaceLocked(SurfaceControl.Transaction t) {
395         final ActivityRecord activity = mWin.mActivityRecord;
396         if (activity != null) {
397             if (mWin == activity.mStartingWindow) {
398                 activity.startingDisplayed = false;
399             }
400         }
401 
402         if (mSurfaceController == null) {
403             return;
404         }
405 
406         mWin.mHidden = true;
407 
408         try {
409             if (DEBUG_VISIBILITY) {
410                 logWithStack(TAG, "Window " + this + " destroying surface "
411                         + mSurfaceController + ", session " + mSession);
412             }
413             ProtoLog.i(WM_SHOW_SURFACE_ALLOC, "SURFACE DESTROY: %s. %s",
414                     mWin, new RuntimeException().fillInStackTrace());
415             destroySurface(t);
416             // Don't hide wallpaper if we're deferring the surface destroy
417             // because of a surface change.
418             mWallpaperControllerLocked.hideWallpapers(mWin);
419         } catch (RuntimeException e) {
420             Slog.w(TAG, "Exception thrown when destroying Window " + this
421                     + " surface " + mSurfaceController + " session " + mSession + ": "
422                     + e.toString());
423         }
424 
425         // Whether the surface was preserved (and copied to mPendingDestroySurface) or not, it
426         // needs to be cleared to match the WindowState.mHasSurface state. It is also necessary
427         // so it can be recreated successfully in mPendingDestroySurface case.
428         mWin.setHasSurface(false);
429         if (mSurfaceController != null) {
430             mSurfaceController.setShown(false);
431         }
432         mSurfaceController = null;
433         mDrawState = NO_SURFACE;
434     }
435 
computeShownFrameLocked()436     void computeShownFrameLocked() {
437         if (mIsWallpaper && mService.mRoot.mWallpaperActionPending) {
438             return;
439         } else if (mWin.isDragResizeChanged()) {
440             // This window is awaiting a relayout because user just started (or ended)
441             // drag-resizing. The shown frame (which affects surface size and pos)
442             // should not be updated until we get next finished draw with the new surface.
443             // Otherwise one or two frames rendered with old settings would be displayed
444             // with new geometry.
445             return;
446         }
447 
448         if (DEBUG) {
449             Slog.v(TAG, "computeShownFrameLocked: " + this
450                     + " not attached, mAlpha=" + mAlpha);
451         }
452 
453         mShownAlpha = mAlpha;
454     }
455 
isInBlastSync()456     private boolean isInBlastSync() {
457         return mService.useBLASTSync() && mWin.useBLASTSync();
458     }
459 
shouldConsumeMainWindowSizeTransaction()460     private boolean shouldConsumeMainWindowSizeTransaction() {
461         // We only consume the transaction when the client is calling relayout
462         // because this is the only time we know the frameNumber will be valid
463         // due to the client renderer being paused. Put otherwise, only when
464         // mInRelayout is true can we guarantee the next frame will contain
465         // the most recent configuration.
466         if (!mWin.mInRelayout) return false;
467         // Since we can only do this for one window, we focus on the main application window
468         if (mAttrType != TYPE_BASE_APPLICATION) return false;
469         final Task task = mWin.getTask();
470         if (task == null) return false;
471         if (task.getMainWindowSizeChangeTransaction() == null) return false;
472         // Likewise we only focus on the task root, since we can only use one window
473         if (!mWin.mActivityRecord.isRootOfTask()) return false;
474         return true;
475     }
476 
setSurfaceBoundariesLocked(SurfaceControl.Transaction t)477     void setSurfaceBoundariesLocked(SurfaceControl.Transaction t) {
478         if (mSurfaceController == null) {
479             return;
480         }
481 
482         final WindowState w = mWin;
483         final Task task = w.getTask();
484         if (shouldConsumeMainWindowSizeTransaction()) {
485             if (isInBlastSync()) {
486                 // If we're in a sync transaction, there's no need to call defer transaction.
487                 // The sync transaction will contain the buffer so the bounds change transaction
488                 // will only be applied with the buffer.
489                 t.merge(task.getMainWindowSizeChangeTransaction());
490                 task.setMainWindowSizeChangeTransaction(null);
491             } else {
492                 mWin.applyWithNextDraw(finishedFrame -> {
493                       final SurfaceControl.Transaction sizeChangedTransaction =
494                           task.getMainWindowSizeChangeTransaction();
495                       if (sizeChangedTransaction != null) {
496                           finishedFrame.merge(sizeChangedTransaction);
497                           task.setMainWindowSizeChangeTransaction(null);
498                       }
499                 });
500             }
501         }
502     }
503 
prepareSurfaceLocked(SurfaceControl.Transaction t)504     void prepareSurfaceLocked(SurfaceControl.Transaction t) {
505         final WindowState w = mWin;
506         if (!hasSurface()) {
507 
508             // There is no need to wait for an animation change if our window is gone for layout
509             // already as we'll never be visible.
510             if (w.getOrientationChanging() && w.isGoneForLayout()) {
511                 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change skips hidden %s", w);
512                 w.setOrientationChanging(false);
513             }
514             return;
515         }
516 
517         boolean displayed = false;
518 
519         computeShownFrameLocked();
520 
521         setSurfaceBoundariesLocked(t);
522 
523         if (w.isParentWindowHidden() || !w.isOnScreen()) {
524             hide(t, "prepareSurfaceLocked");
525             mWallpaperControllerLocked.hideWallpapers(w);
526 
527             // If we are waiting for this window to handle an orientation change. If this window is
528             // really hidden (gone for layout), there is no point in still waiting for it.
529             // Note that this does introduce a potential glitch if the window becomes unhidden
530             // before it has drawn for the new orientation.
531             if (w.getOrientationChanging() && w.isGoneForLayout()) {
532                 w.setOrientationChanging(false);
533                 ProtoLog.v(WM_DEBUG_ORIENTATION,
534                         "Orientation change skips hidden %s", w);
535             }
536         } else if (mLastAlpha != mShownAlpha
537                 || mLastHidden) {
538             displayed = true;
539             mLastAlpha = mShownAlpha;
540             ProtoLog.i(WM_SHOW_TRANSACTIONS,
541                     "SURFACE controller=%s alpha=%f HScale=%f, VScale=%f: %s",
542                     mSurfaceController, mShownAlpha, w.mHScale, w.mVScale, w);
543 
544             boolean prepared =
545                 mSurfaceController.prepareToShowInTransaction(t, mShownAlpha);
546 
547             if (prepared && mDrawState == HAS_DRAWN) {
548                 if (mLastHidden) {
549                     if (showSurfaceRobustlyLocked(t)) {
550                         mAnimator.requestRemovalOfReplacedWindows(w);
551                         mLastHidden = false;
552                         final DisplayContent displayContent = w.getDisplayContent();
553                         if (!displayContent.getLastHasContent()) {
554                             // This draw means the difference between unique content and mirroring.
555                             // Run another pass through performLayout to set mHasContent in the
556                             // LogicalDisplay.
557                             displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
558                             if (DEBUG_LAYOUT_REPEATS) {
559                                 mService.mWindowPlacerLocked.debugLayoutRepeats(
560                                         "showSurfaceRobustlyLocked " + w,
561                                         displayContent.pendingLayoutChanges);
562                             }
563                         }
564                     } else {
565                         w.setOrientationChanging(false);
566                     }
567                 }
568             }
569             if (hasSurface()) {
570                 w.mToken.hasVisible = true;
571             }
572         } else {
573             if (DEBUG_ANIM && mWin.isAnimating(TRANSITION | PARENTS)) {
574                 Slog.v(TAG, "prepareSurface: No changes in animation for " + this);
575             }
576             displayed = true;
577         }
578 
579         if (w.getOrientationChanging()) {
580             if (!w.isDrawn()) {
581                 if (w.mDisplayContent.waitForUnfreeze(w)) {
582                     w.mWmService.mRoot.mOrientationChangeComplete = false;
583                     mAnimator.mLastWindowFreezeSource = w;
584                 }
585                 ProtoLog.v(WM_DEBUG_ORIENTATION,
586                         "Orientation continue waiting for draw in %s", w);
587             } else {
588                 w.setOrientationChanging(false);
589                 ProtoLog.v(WM_DEBUG_ORIENTATION, "Orientation change complete in %s", w);
590             }
591         }
592 
593         if (displayed) {
594             w.mToken.hasVisible = true;
595         }
596     }
597 
598     /**
599      * Try to change the pixel format without recreating the surface. This
600      * will be common in the case of changing from PixelFormat.OPAQUE to
601      * PixelFormat.TRANSLUCENT in the hardware-accelerated case as both
602      * requested formats resolve to the same underlying SurfaceControl format
603      * @return True if format was succesfully changed, false otherwise
604      */
tryChangeFormatInPlaceLocked()605     boolean tryChangeFormatInPlaceLocked() {
606         if (mSurfaceController == null) {
607             return false;
608         }
609         final LayoutParams attrs = mWin.getAttrs();
610         final boolean isHwAccelerated = (attrs.flags & FLAG_HARDWARE_ACCELERATED) != 0;
611         final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
612         if (format == mSurfaceFormat) {
613             setOpaqueLocked(!PixelFormat.formatHasAlpha(attrs.format));
614             return true;
615         }
616         return false;
617     }
618 
setOpaqueLocked(boolean isOpaque)619     void setOpaqueLocked(boolean isOpaque) {
620         if (mSurfaceController == null) {
621             return;
622         }
623         mSurfaceController.setOpaque(isOpaque);
624     }
625 
setSecureLocked(boolean isSecure)626     void setSecureLocked(boolean isSecure) {
627         if (mSurfaceController == null) {
628             return;
629         }
630         mSurfaceController.setSecure(isSecure);
631     }
632 
setColorSpaceAgnosticLocked(boolean agnostic)633     void setColorSpaceAgnosticLocked(boolean agnostic) {
634         if (mSurfaceController == null) {
635             return;
636         }
637         mSurfaceController.setColorSpaceAgnostic(agnostic);
638     }
639 
640     /**
641      * Have the surface flinger show a surface, robustly dealing with
642      * error conditions.  In particular, if there is not enough memory
643      * to show the surface, then we will try to get rid of other surfaces
644      * in order to succeed.
645      *
646      * @return Returns true if the surface was successfully shown.
647      */
showSurfaceRobustlyLocked(SurfaceControl.Transaction t)648     private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
649         boolean shown = mSurfaceController.showRobustly(t);
650         if (!shown)
651             return false;
652 
653         t.merge(mPostDrawTransaction);
654         return true;
655     }
656 
applyEnterAnimationLocked()657     void applyEnterAnimationLocked() {
658         // If we are the new part of a window replacement transition and we have requested
659         // not to animate, we instead want to make it seamless, so we don't want to apply
660         // an enter transition.
661         if (mWin.mSkipEnterAnimationForSeamlessReplacement) {
662             return;
663         }
664 
665         final int transit;
666         if (mEnterAnimationPending) {
667             mEnterAnimationPending = false;
668             transit = WindowManagerPolicy.TRANSIT_ENTER;
669         } else {
670             transit = WindowManagerPolicy.TRANSIT_SHOW;
671         }
672 
673         // We don't apply animation for application main window here since this window type
674         // should be controlled by ActivityRecord in general. Wallpaper is also excluded because
675         // WallpaperController should handle it.
676         if (mAttrType != TYPE_BASE_APPLICATION && !mIsWallpaper) {
677             applyAnimationLocked(transit, true);
678         }
679 
680         if (mService.mAccessibilityController.hasCallbacks()) {
681             mService.mAccessibilityController.onWindowTransition(mWin, transit);
682         }
683     }
684 
685     /**
686      * Choose the correct animation and set it to the passed WindowState.
687      * @param transit If AppTransition.TRANSIT_PREVIEW_DONE and the app window has been drawn
688      *      then the animation will be app_starting_exit. Any other value loads the animation from
689      *      the switch statement below.
690      * @param isEntrance The animation type the last time this was called. Used to keep from
691      *      loading the same animation twice.
692      * @return true if an animation has been loaded.
693      */
applyAnimationLocked(int transit, boolean isEntrance)694     boolean applyAnimationLocked(int transit, boolean isEntrance) {
695         if (mWin.isAnimating() && mAnimationIsEntrance == isEntrance) {
696             // If we are trying to apply an animation, but already running
697             // an animation of the same type, then just leave that one alone.
698             return true;
699         }
700 
701         final boolean isImeWindow = mWin.mAttrs.type == TYPE_INPUT_METHOD;
702         if (isEntrance && isImeWindow) {
703             mWin.getDisplayContent().adjustForImeIfNeeded();
704             mWin.setDisplayLayoutNeeded();
705             mService.mWindowPlacerLocked.requestTraversal();
706         }
707 
708         // Only apply an animation if the display isn't frozen.  If it is
709         // frozen, there is no reason to animate and it can cause strange
710         // artifacts when we unfreeze the display if some different animation
711         // is running.
712         if (mWin.mToken.okToAnimate()) {
713             int anim = mWin.getDisplayContent().getDisplayPolicy().selectAnimation(mWin, transit);
714             int attr = -1;
715             Animation a = null;
716             if (anim != DisplayPolicy.ANIMATION_STYLEABLE) {
717                 if (anim != DisplayPolicy.ANIMATION_NONE) {
718                     Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#loadAnimation");
719                     a = AnimationUtils.loadAnimation(mContext, anim);
720                     Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
721                 }
722             } else {
723                 switch (transit) {
724                     case WindowManagerPolicy.TRANSIT_ENTER:
725                         attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
726                         break;
727                     case WindowManagerPolicy.TRANSIT_EXIT:
728                         attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
729                         break;
730                     case WindowManagerPolicy.TRANSIT_SHOW:
731                         attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
732                         break;
733                     case WindowManagerPolicy.TRANSIT_HIDE:
734                         attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
735                         break;
736                 }
737                 if (attr >= 0) {
738                     a = mWin.getDisplayContent().mAppTransition.loadAnimationAttr(
739                             mWin.mAttrs, attr, TRANSIT_OLD_NONE);
740                 }
741             }
742             if (DEBUG_ANIM) Slog.v(TAG,
743                     "applyAnimation: win=" + this
744                     + " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
745                     + " a=" + a
746                     + " transit=" + transit
747                     + " type=" + mAttrType
748                     + " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
749             if (a != null) {
750                 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
751                 Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "WSA#startAnimation");
752                 mWin.startAnimation(a);
753                 Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
754                 mAnimationIsEntrance = isEntrance;
755             }
756         } else if (!isImeWindow) {
757             mWin.cancelAnimation();
758         }
759 
760         if (!isEntrance && isImeWindow) {
761             mWin.getDisplayContent().adjustForImeIfNeeded();
762         }
763 
764         return mWin.isAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION);
765     }
766 
dumpDebug(ProtoOutputStream proto, long fieldId)767     void dumpDebug(ProtoOutputStream proto, long fieldId) {
768         final long token = proto.start(fieldId);
769         if (mSurfaceController != null) {
770             mSurfaceController.dumpDebug(proto, SURFACE);
771         }
772         proto.write(DRAW_STATE, mDrawState);
773         mSystemDecorRect.dumpDebug(proto, SYSTEM_DECOR_RECT);
774         proto.end(token);
775     }
776 
dump(PrintWriter pw, String prefix, boolean dumpAll)777     public void dump(PrintWriter pw, String prefix, boolean dumpAll) {
778         if (mAnimationIsEntrance) {
779             pw.print(prefix); pw.print(" mAnimationIsEntrance="); pw.print(mAnimationIsEntrance);
780         }
781         if (mSurfaceController != null) {
782             mSurfaceController.dump(pw, prefix, dumpAll);
783         }
784         if (dumpAll) {
785             pw.print(prefix); pw.print("mDrawState="); pw.print(drawStateToString());
786             pw.print(prefix); pw.print(" mLastHidden="); pw.println(mLastHidden);
787             pw.print(prefix); pw.print("mEnterAnimationPending=" + mEnterAnimationPending);
788             pw.print(prefix); pw.print("mSystemDecorRect="); mSystemDecorRect.printShortString(pw);
789 
790             pw.println();
791         }
792 
793         if (mShownAlpha != 1 || mAlpha != 1 || mLastAlpha != 1) {
794             pw.print(prefix); pw.print("mShownAlpha="); pw.print(mShownAlpha);
795                     pw.print(" mAlpha="); pw.print(mAlpha);
796                     pw.print(" mLastAlpha="); pw.println(mLastAlpha);
797         }
798         if (mWin.mGlobalScale != 1) {
799             pw.print(prefix); pw.print("mGlobalScale="); pw.print(mWin.mGlobalScale);
800         }
801     }
802 
803     @Override
toString()804     public String toString() {
805         StringBuffer sb = new StringBuffer("WindowStateAnimator{");
806         sb.append(Integer.toHexString(System.identityHashCode(this)));
807         sb.append(' ');
808         sb.append(mWin.mAttrs.getTitle());
809         sb.append('}');
810         return sb.toString();
811     }
812 
getShown()813     boolean getShown() {
814         if (mSurfaceController != null) {
815             return mSurfaceController.getShown();
816         }
817         return false;
818     }
819 
destroySurface(SurfaceControl.Transaction t)820     void destroySurface(SurfaceControl.Transaction t) {
821         // Since the SurfaceControl is getting torn down, it's safe to just clean up any
822         // pending transactions that were in mPostDrawTransaction, as well.
823         t.merge(mPostDrawTransaction);
824 
825         try {
826             if (mSurfaceController != null) {
827                 mSurfaceController.destroy(t);
828             }
829         } catch (RuntimeException e) {
830             Slog.w(TAG, "Exception thrown when destroying surface " + this
831                     + " surface " + mSurfaceController + " session " + mSession + ": " + e);
832         } finally {
833             mWin.setHasSurface(false);
834             mSurfaceController = null;
835             mDrawState = NO_SURFACE;
836         }
837     }
838 
getSurfaceControl()839     SurfaceControl getSurfaceControl() {
840         if (!hasSurface()) {
841             return null;
842         }
843         return mSurfaceController.mSurfaceControl;
844     }
845 }
846