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