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