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 com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS; 20 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; 21 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; 22 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS; 23 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATION; 24 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; 25 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 27 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 29 30 import android.content.Context; 31 import android.os.Trace; 32 import android.util.Slog; 33 import android.util.TimeUtils; 34 import android.view.Choreographer; 35 import android.view.SurfaceControl; 36 37 import com.android.internal.protolog.common.ProtoLog; 38 import com.android.server.policy.WindowManagerPolicy; 39 40 import java.io.PrintWriter; 41 import java.util.ArrayList; 42 43 /** 44 * Singleton class that carries out the animations and Surface operations in a separate task 45 * on behalf of WindowManagerService. 46 */ 47 public class WindowAnimator { 48 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowAnimator" : TAG_WM; 49 50 final WindowManagerService mService; 51 final Context mContext; 52 final WindowManagerPolicy mPolicy; 53 54 /** Is any window animating? */ 55 private boolean mLastRootAnimating; 56 57 /** True if we are running any animations that require expensive composition. */ 58 private boolean mRunningExpensiveAnimations; 59 60 final Choreographer.FrameCallback mAnimationFrameCallback; 61 62 /** Time of current animation step. Reset on each iteration */ 63 long mCurrentTime; 64 65 int mBulkUpdateParams = 0; 66 Object mLastWindowFreezeSource; 67 68 private boolean mInitialized = false; 69 70 private Choreographer mChoreographer; 71 72 /** 73 * Indicates whether we have an animation frame callback scheduled, which will happen at 74 * vsync-app and then schedule the animation tick at the right time (vsync-sf). 75 */ 76 private boolean mAnimationFrameCallbackScheduled; 77 boolean mNotifyWhenNoAnimation = false; 78 79 /** 80 * A list of runnable that need to be run after {@link WindowContainer#prepareSurfaces} is 81 * executed and the corresponding transaction is closed and applied. 82 */ 83 private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>(); 84 private boolean mInExecuteAfterPrepareSurfacesRunnables; 85 86 private final SurfaceControl.Transaction mTransaction; 87 WindowAnimator(final WindowManagerService service)88 WindowAnimator(final WindowManagerService service) { 89 mService = service; 90 mContext = service.mContext; 91 mPolicy = service.mPolicy; 92 mTransaction = service.mTransactionFactory.get(); 93 service.mAnimationHandler.runWithScissors( 94 () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */); 95 96 mAnimationFrameCallback = frameTimeNs -> { 97 synchronized (mService.mGlobalLock) { 98 mAnimationFrameCallbackScheduled = false; 99 animate(frameTimeNs); 100 if (mNotifyWhenNoAnimation && !mLastRootAnimating) { 101 mService.mGlobalLock.notifyAll(); 102 } 103 } 104 }; 105 } 106 ready()107 void ready() { 108 mInitialized = true; 109 } 110 animate(long frameTimeNs)111 private void animate(long frameTimeNs) { 112 if (!mInitialized) { 113 return; 114 } 115 116 // Schedule next frame already such that back-pressure happens continuously. 117 scheduleAnimation(); 118 119 final RootWindowContainer root = mService.mRoot; 120 mCurrentTime = frameTimeNs / TimeUtils.NANOS_PER_MS; 121 mBulkUpdateParams = 0; 122 root.mOrientationChangeComplete = true; 123 if (DEBUG_WINDOW_TRACE) { 124 Slog.i(TAG, "!!! animate: entry time=" + mCurrentTime); 125 } 126 127 ProtoLog.i(WM_SHOW_TRANSACTIONS, ">>> OPEN TRANSACTION animate"); 128 mService.openSurfaceTransaction(); 129 try { 130 // Remove all deferred displays, tasks, and activities. 131 root.handleCompleteDeferredRemoval(); 132 133 final AccessibilityController accessibilityController = 134 mService.mAccessibilityController; 135 final int numDisplays = root.getChildCount(); 136 for (int i = 0; i < numDisplays; i++) { 137 final DisplayContent dc = root.getChildAt(i); 138 // Update animations of all applications, including those associated with 139 // exiting/removed apps. 140 dc.updateWindowsForAnimator(); 141 dc.prepareSurfaces(); 142 } 143 144 for (int i = 0; i < numDisplays; i++) { 145 final DisplayContent dc = root.getChildAt(i); 146 147 dc.checkAppWindowsReadyToShow(); 148 if (accessibilityController.hasCallbacks()) { 149 accessibilityController.drawMagnifiedRegionBorderIfNeeded(dc.mDisplayId, 150 mTransaction); 151 } 152 } 153 154 cancelAnimation(); 155 156 if (mService.mWatermark != null) { 157 mService.mWatermark.drawIfNeeded(); 158 } 159 160 } catch (RuntimeException e) { 161 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 162 } 163 164 final boolean hasPendingLayoutChanges = root.hasPendingLayoutChanges(this); 165 final boolean doRequest = (mBulkUpdateParams != 0 || root.mOrientationChangeComplete) 166 && root.copyAnimToLayoutParams(); 167 if (hasPendingLayoutChanges || doRequest) { 168 mService.mWindowPlacerLocked.requestTraversal(); 169 } 170 171 final boolean rootAnimating = root.isAnimating(TRANSITION | CHILDREN /* flags */, 172 ANIMATION_TYPE_ALL /* typesToCheck */); 173 if (rootAnimating && !mLastRootAnimating) { 174 Trace.asyncTraceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0); 175 } 176 if (!rootAnimating && mLastRootAnimating) { 177 mService.mWindowPlacerLocked.requestTraversal(); 178 Trace.asyncTraceEnd(Trace.TRACE_TAG_WINDOW_MANAGER, "animating", 0); 179 } 180 mLastRootAnimating = rootAnimating; 181 182 final boolean runningExpensiveAnimations = 183 root.isAnimating(TRANSITION | CHILDREN /* flags */, 184 ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_SCREEN_ROTATION 185 | ANIMATION_TYPE_RECENTS /* typesToCheck */); 186 if (runningExpensiveAnimations && !mRunningExpensiveAnimations) { 187 // Usually app transitions put quite a load onto the system already (with all the things 188 // happening in app), so pause snapshot persisting to not increase the load. 189 mService.mSnapshotController.setPause(true); 190 mTransaction.setEarlyWakeupStart(); 191 } else if (!runningExpensiveAnimations && mRunningExpensiveAnimations) { 192 mService.mSnapshotController.setPause(false); 193 mTransaction.setEarlyWakeupEnd(); 194 } 195 mRunningExpensiveAnimations = runningExpensiveAnimations; 196 197 SurfaceControl.mergeToGlobalTransaction(mTransaction); 198 mService.closeSurfaceTransaction("WindowAnimator"); 199 ProtoLog.i(WM_SHOW_TRANSACTIONS, "<<< CLOSE TRANSACTION animate"); 200 201 mService.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); 202 executeAfterPrepareSurfacesRunnables(); 203 204 if (DEBUG_WINDOW_TRACE) { 205 Slog.i(TAG, "!!! animate: exit" 206 + " mBulkUpdateParams=" + Integer.toHexString(mBulkUpdateParams) 207 + " hasPendingLayoutChanges=" + hasPendingLayoutChanges); 208 } 209 } 210 bulkUpdateParamsToString(int bulkUpdateParams)211 private static String bulkUpdateParamsToString(int bulkUpdateParams) { 212 StringBuilder builder = new StringBuilder(128); 213 if ((bulkUpdateParams & WindowSurfacePlacer.SET_UPDATE_ROTATION) != 0) { 214 builder.append(" UPDATE_ROTATION"); 215 } 216 if ((bulkUpdateParams & WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING) != 0) { 217 builder.append(" SET_WALLPAPER_ACTION_PENDING"); 218 } 219 return builder.toString(); 220 } 221 dumpLocked(PrintWriter pw, String prefix, boolean dumpAll)222 public void dumpLocked(PrintWriter pw, String prefix, boolean dumpAll) { 223 final String subPrefix = " " + prefix; 224 225 for (int i = 0; i < mService.mRoot.getChildCount(); i++) { 226 final DisplayContent dc = mService.mRoot.getChildAt(i); 227 pw.print(prefix); pw.print(dc); pw.println(":"); 228 dc.dumpWindowAnimators(pw, subPrefix); 229 pw.println(); 230 } 231 232 pw.println(); 233 234 if (dumpAll) { 235 pw.print(prefix); pw.print("mCurrentTime="); 236 pw.println(TimeUtils.formatUptime(mCurrentTime)); 237 } 238 if (mBulkUpdateParams != 0) { 239 pw.print(prefix); pw.print("mBulkUpdateParams=0x"); 240 pw.print(Integer.toHexString(mBulkUpdateParams)); 241 pw.println(bulkUpdateParamsToString(mBulkUpdateParams)); 242 } 243 } 244 scheduleAnimation()245 void scheduleAnimation() { 246 if (!mAnimationFrameCallbackScheduled) { 247 mAnimationFrameCallbackScheduled = true; 248 mChoreographer.postFrameCallback(mAnimationFrameCallback); 249 } 250 } 251 cancelAnimation()252 private void cancelAnimation() { 253 if (mAnimationFrameCallbackScheduled) { 254 mAnimationFrameCallbackScheduled = false; 255 mChoreographer.removeFrameCallback(mAnimationFrameCallback); 256 } 257 } 258 isAnimationScheduled()259 boolean isAnimationScheduled() { 260 return mAnimationFrameCallbackScheduled; 261 } 262 getChoreographer()263 Choreographer getChoreographer() { 264 return mChoreographer; 265 } 266 267 /** 268 * Adds a runnable to be executed after {@link WindowContainer#prepareSurfaces} is called and 269 * the corresponding transaction is closed and applied. 270 */ addAfterPrepareSurfacesRunnable(Runnable r)271 void addAfterPrepareSurfacesRunnable(Runnable r) { 272 // If runnables are already being handled in executeAfterPrepareSurfacesRunnable, then just 273 // immediately execute the runnable passed in. 274 if (mInExecuteAfterPrepareSurfacesRunnables) { 275 r.run(); 276 return; 277 } 278 279 mAfterPrepareSurfacesRunnables.add(r); 280 scheduleAnimation(); 281 } 282 executeAfterPrepareSurfacesRunnables()283 void executeAfterPrepareSurfacesRunnables() { 284 285 // Don't even think about to start recursing! 286 if (mInExecuteAfterPrepareSurfacesRunnables) { 287 return; 288 } 289 mInExecuteAfterPrepareSurfacesRunnables = true; 290 291 // Traverse in order they were added. 292 final int size = mAfterPrepareSurfacesRunnables.size(); 293 for (int i = 0; i < size; i++) { 294 mAfterPrepareSurfacesRunnables.get(i).run(); 295 } 296 mAfterPrepareSurfacesRunnables.clear(); 297 mInExecuteAfterPrepareSurfacesRunnables = false; 298 } 299 } 300