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