1 /* 2 * Copyright (C) 2021 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.TRANSIT_OLD_KEYGUARD_GOING_AWAY; 20 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; 21 import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; 22 import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT; 23 import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE; 24 25 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; 26 import static com.android.server.wm.AnimationAdapterProto.REMOTE; 27 import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; 28 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; 29 30 import android.graphics.Rect; 31 import android.os.SystemClock; 32 import android.util.proto.ProtoOutputStream; 33 import android.view.RemoteAnimationTarget; 34 import android.view.SurfaceControl; 35 import android.view.WindowManager; 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 class NonAppWindowAnimationAdapter implements AnimationAdapter { 44 45 private final WindowContainer mWindowContainer; 46 private RemoteAnimationTarget mTarget; 47 private SurfaceControl mCapturedLeash; 48 private SurfaceAnimator.OnAnimationFinishedCallback mCapturedLeashFinishCallback; 49 private @SurfaceAnimator.AnimationType int mLastAnimationType; 50 51 private long mDurationHint; 52 private long mStatusBarTransitionDelay; 53 54 @Override getShowWallpaper()55 public boolean getShowWallpaper() { 56 return false; 57 } 58 NonAppWindowAnimationAdapter(WindowContainer w, long durationHint, long statusBarTransitionDelay)59 NonAppWindowAnimationAdapter(WindowContainer w, long durationHint, 60 long statusBarTransitionDelay) { 61 mWindowContainer = w; 62 mDurationHint = durationHint; 63 mStatusBarTransitionDelay = statusBarTransitionDelay; 64 } 65 startNonAppWindowAnimations(WindowManagerService service, DisplayContent displayContent, @WindowManager.TransitionOldType int transit, long durationHint, long statusBarTransitionDelay, ArrayList<NonAppWindowAnimationAdapter> adaptersOut)66 static RemoteAnimationTarget[] startNonAppWindowAnimations(WindowManagerService service, 67 DisplayContent displayContent, @WindowManager.TransitionOldType int transit, 68 long durationHint, long statusBarTransitionDelay, 69 ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { 70 final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>(); 71 if (transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY 72 || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER) { 73 startNonAppWindowAnimationsForKeyguardExit( 74 service, durationHint, statusBarTransitionDelay, targets, adaptersOut); 75 } else if (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT 76 || transit == TRANSIT_OLD_WALLPAPER_CLOSE) { 77 final boolean shouldAttachNavBarToApp = 78 displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() 79 && service.getRecentsAnimationController() == null 80 && displayContent.getFadeRotationAnimationController() == null; 81 if (shouldAttachNavBarToApp) { 82 startNavigationBarWindowAnimation( 83 displayContent, durationHint, statusBarTransitionDelay, targets, 84 adaptersOut); 85 } 86 } 87 return targets.toArray(new RemoteAnimationTarget[targets.size()]); 88 } 89 90 /** 91 * Creates and starts remote animations for all the visible non app windows. 92 * 93 * @return RemoteAnimationTarget[] targets for all the visible non app windows 94 */ startNonAppWindowAnimationsForKeyguardExit(WindowManagerService service, long durationHint, long statusBarTransitionDelay, ArrayList<RemoteAnimationTarget> targets, ArrayList<NonAppWindowAnimationAdapter> adaptersOut)95 private static void startNonAppWindowAnimationsForKeyguardExit(WindowManagerService service, 96 long durationHint, long statusBarTransitionDelay, 97 ArrayList<RemoteAnimationTarget> targets, 98 ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { 99 100 final WindowManagerPolicy policy = service.mPolicy; 101 service.mRoot.forAllWindows(nonAppWindow -> { 102 // Animation on the IME window is controlled via Insets. 103 if (nonAppWindow.mActivityRecord == null && policy.canBeHiddenByKeyguardLw(nonAppWindow) 104 && nonAppWindow.wouldBeVisibleIfPolicyIgnored() && !nonAppWindow.isVisible() 105 && nonAppWindow != service.mRoot.getCurrentInputMethodWindow()) { 106 final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter( 107 nonAppWindow, durationHint, statusBarTransitionDelay); 108 adaptersOut.add(nonAppAdapter); 109 nonAppWindow.startAnimation(nonAppWindow.getPendingTransaction(), 110 nonAppAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); 111 targets.add(nonAppAdapter.createRemoteAnimationTarget()); 112 } 113 }, true /* traverseTopToBottom */); 114 } 115 116 /** 117 * Creates and starts remote animation for the navigation bar windows. 118 * 119 * @return RemoteAnimationTarget[] targets for all the visible non app windows 120 */ startNavigationBarWindowAnimation(DisplayContent displayContent, long durationHint, long statusBarTransitionDelay, ArrayList<RemoteAnimationTarget> targets, ArrayList<NonAppWindowAnimationAdapter> adaptersOut)121 private static void startNavigationBarWindowAnimation(DisplayContent displayContent, 122 long durationHint, long statusBarTransitionDelay, 123 ArrayList<RemoteAnimationTarget> targets, 124 ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { 125 final WindowState navWindow = displayContent.getDisplayPolicy().getNavigationBar(); 126 final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter( 127 navWindow.mToken, durationHint, statusBarTransitionDelay); 128 adaptersOut.add(nonAppAdapter); 129 navWindow.mToken.startAnimation(navWindow.mToken.getPendingTransaction(), 130 nonAppAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); 131 targets.add(nonAppAdapter.createRemoteAnimationTarget()); 132 } 133 134 /** 135 * Create a remote animation target for this animation adapter. 136 */ createRemoteAnimationTarget()137 RemoteAnimationTarget createRemoteAnimationTarget() { 138 mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false, 139 new Rect(), null, mWindowContainer.getPrefixOrderIndex(), 140 mWindowContainer.getLastSurfacePosition(), mWindowContainer.getBounds(), null, 141 mWindowContainer.getWindowConfiguration(), true, null, null, null, 142 mWindowContainer.getWindowType()); 143 return mTarget; 144 } 145 146 @Override startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback)147 public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, 148 int type, SurfaceAnimator.OnAnimationFinishedCallback finishCallback) { 149 ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation"); 150 mCapturedLeash = animationLeash; 151 mCapturedLeashFinishCallback = finishCallback; 152 mLastAnimationType = type; 153 } 154 155 /** 156 * @return the callback to call to clean up when the animation has finished. 157 */ getLeashFinishedCallback()158 SurfaceAnimator.OnAnimationFinishedCallback getLeashFinishedCallback() { 159 return mCapturedLeashFinishCallback; 160 } 161 162 /** 163 * @return the type of animation. 164 */ 165 @SurfaceAnimator.AnimationType getLastAnimationType()166 int getLastAnimationType() { 167 return mLastAnimationType; 168 } 169 getWindowContainer()170 WindowContainer getWindowContainer() { 171 return mWindowContainer; 172 } 173 174 @Override getDurationHint()175 public long getDurationHint() { 176 return mDurationHint; 177 } 178 179 @Override getStatusBarTransitionsStartTime()180 public long getStatusBarTransitionsStartTime() { 181 return SystemClock.uptimeMillis() + mStatusBarTransitionDelay; 182 } 183 184 /** 185 * @return the leash for this animation (only valid after the non app window surface animation 186 * has started). 187 */ getLeash()188 SurfaceControl getLeash() { 189 return mCapturedLeash; 190 } 191 192 @Override onAnimationCancelled(SurfaceControl animationLeash)193 public void onAnimationCancelled(SurfaceControl animationLeash) { 194 ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "onAnimationCancelled"); 195 } 196 197 @Override dump(PrintWriter pw, String prefix)198 public void dump(PrintWriter pw, String prefix) { 199 pw.print(prefix); 200 pw.print("windowContainer="); 201 pw.println(mWindowContainer); 202 if (mTarget != null) { 203 pw.print(prefix); 204 pw.println("Target:"); 205 mTarget.dump(pw, prefix + " "); 206 } else { 207 pw.print(prefix); 208 pw.println("Target: null"); 209 } 210 } 211 212 @Override dumpDebug(ProtoOutputStream proto)213 public void dumpDebug(ProtoOutputStream proto) { 214 final long token = proto.start(REMOTE); 215 if (mTarget != null) { 216 mTarget.dumpDebug(proto, TARGET); 217 } 218 proto.end(token); 219 } 220 } 221