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