| /* |
| * Copyright (C) 2021 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.server.wm; |
| |
| import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY; |
| import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; |
| import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN; |
| import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT; |
| import static android.view.WindowManager.TRANSIT_OLD_WALLPAPER_CLOSE; |
| |
| import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_REMOTE_ANIMATIONS; |
| import static com.android.server.wm.AnimationAdapterProto.REMOTE; |
| import static com.android.server.wm.RemoteAnimationAdapterWrapperProto.TARGET; |
| import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION; |
| |
| import android.annotation.NonNull; |
| import android.graphics.Rect; |
| import android.os.SystemClock; |
| import android.util.proto.ProtoOutputStream; |
| import android.view.RemoteAnimationTarget; |
| import android.view.SurfaceControl; |
| import android.view.WindowManager; |
| |
| import com.android.internal.protolog.common.ProtoLog; |
| import com.android.server.policy.WindowManagerPolicy; |
| |
| import java.io.PrintWriter; |
| import java.util.ArrayList; |
| |
| class NonAppWindowAnimationAdapter implements AnimationAdapter { |
| |
| private final WindowContainer mWindowContainer; |
| private RemoteAnimationTarget mTarget; |
| private SurfaceControl mCapturedLeash; |
| private SurfaceAnimator.OnAnimationFinishedCallback mCapturedLeashFinishCallback; |
| private @SurfaceAnimator.AnimationType int mLastAnimationType; |
| |
| private long mDurationHint; |
| private long mStatusBarTransitionDelay; |
| |
| @Override |
| public boolean getShowWallpaper() { |
| return false; |
| } |
| |
| NonAppWindowAnimationAdapter(WindowContainer w, long durationHint, |
| long statusBarTransitionDelay) { |
| mWindowContainer = w; |
| mDurationHint = durationHint; |
| mStatusBarTransitionDelay = statusBarTransitionDelay; |
| } |
| |
| static RemoteAnimationTarget[] startNonAppWindowAnimations(WindowManagerService service, |
| DisplayContent displayContent, @WindowManager.TransitionOldType int transit, |
| long durationHint, long statusBarTransitionDelay, |
| ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { |
| final ArrayList<RemoteAnimationTarget> targets = new ArrayList<>(); |
| if (shouldStartNonAppWindowAnimationsForKeyguardExit(transit)) { |
| startNonAppWindowAnimationsForKeyguardExit( |
| service, durationHint, statusBarTransitionDelay, targets, adaptersOut); |
| } else if (shouldAttachNavBarToApp(service, displayContent, transit)) { |
| startNavigationBarWindowAnimation( |
| displayContent, durationHint, statusBarTransitionDelay, targets, |
| adaptersOut); |
| } |
| return targets.toArray(new RemoteAnimationTarget[targets.size()]); |
| } |
| |
| static boolean shouldStartNonAppWindowAnimationsForKeyguardExit( |
| @WindowManager.TransitionOldType int transit) { |
| return transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY |
| || transit == TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER; |
| } |
| |
| static boolean shouldAttachNavBarToApp(WindowManagerService service, |
| DisplayContent displayContent, @WindowManager.TransitionOldType int transit) { |
| return (transit == TRANSIT_OLD_TASK_OPEN || transit == TRANSIT_OLD_TASK_TO_FRONT |
| || transit == TRANSIT_OLD_WALLPAPER_CLOSE) |
| && displayContent.getDisplayPolicy().shouldAttachNavBarToAppDuringTransition() |
| && service.getRecentsAnimationController() == null |
| && displayContent.getAsyncRotationController() == null; |
| } |
| |
| /** |
| * Creates and starts remote animations for all the visible non app windows. |
| * |
| * @return RemoteAnimationTarget[] targets for all the visible non app windows |
| */ |
| private static void startNonAppWindowAnimationsForKeyguardExit(WindowManagerService service, |
| long durationHint, long statusBarTransitionDelay, |
| ArrayList<RemoteAnimationTarget> targets, |
| ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { |
| |
| final WindowManagerPolicy policy = service.mPolicy; |
| service.mRoot.forAllWindows(nonAppWindow -> { |
| // Animation on the IME window is controlled via Insets. |
| if (nonAppWindow.mActivityRecord == null && nonAppWindow.canBeHiddenByKeyguard() |
| && nonAppWindow.wouldBeVisibleIfPolicyIgnored() && !nonAppWindow.isVisible() |
| && nonAppWindow != service.mRoot.getCurrentInputMethodWindow()) { |
| final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter( |
| nonAppWindow, durationHint, statusBarTransitionDelay); |
| adaptersOut.add(nonAppAdapter); |
| nonAppWindow.startAnimation(nonAppWindow.getPendingTransaction(), |
| nonAppAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); |
| targets.add(nonAppAdapter.createRemoteAnimationTarget()); |
| } |
| }, true /* traverseTopToBottom */); |
| } |
| |
| /** |
| * Creates and starts remote animation for the navigation bar windows. |
| * |
| * @return RemoteAnimationTarget[] targets for all the visible non app windows |
| */ |
| private static void startNavigationBarWindowAnimation(DisplayContent displayContent, |
| long durationHint, long statusBarTransitionDelay, |
| ArrayList<RemoteAnimationTarget> targets, |
| ArrayList<NonAppWindowAnimationAdapter> adaptersOut) { |
| final WindowState navWindow = displayContent.getDisplayPolicy().getNavigationBar(); |
| final NonAppWindowAnimationAdapter nonAppAdapter = new NonAppWindowAnimationAdapter( |
| navWindow.mToken, durationHint, statusBarTransitionDelay); |
| adaptersOut.add(nonAppAdapter); |
| navWindow.mToken.startAnimation(navWindow.mToken.getPendingTransaction(), |
| nonAppAdapter, false /* hidden */, ANIMATION_TYPE_WINDOW_ANIMATION); |
| targets.add(nonAppAdapter.createRemoteAnimationTarget()); |
| } |
| |
| /** |
| * Create a remote animation target for this animation adapter. |
| */ |
| RemoteAnimationTarget createRemoteAnimationTarget() { |
| mTarget = new RemoteAnimationTarget(-1, -1, getLeash(), false, |
| new Rect(), null, mWindowContainer.getPrefixOrderIndex(), |
| mWindowContainer.getLastSurfacePosition(), mWindowContainer.getBounds(), null, |
| mWindowContainer.getWindowConfiguration(), true, null, null, null, false, |
| mWindowContainer.getWindowType()); |
| return mTarget; |
| } |
| |
| @Override |
| public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, |
| int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) { |
| ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "startAnimation"); |
| mCapturedLeash = animationLeash; |
| mCapturedLeashFinishCallback = finishCallback; |
| mLastAnimationType = type; |
| } |
| |
| /** |
| * @return the callback to call to clean up when the animation has finished. |
| */ |
| SurfaceAnimator.OnAnimationFinishedCallback getLeashFinishedCallback() { |
| return mCapturedLeashFinishCallback; |
| } |
| |
| /** |
| * @return the type of animation. |
| */ |
| @SurfaceAnimator.AnimationType |
| int getLastAnimationType() { |
| return mLastAnimationType; |
| } |
| |
| WindowContainer getWindowContainer() { |
| return mWindowContainer; |
| } |
| |
| @Override |
| public long getDurationHint() { |
| return mDurationHint; |
| } |
| |
| @Override |
| public long getStatusBarTransitionsStartTime() { |
| return SystemClock.uptimeMillis() + mStatusBarTransitionDelay; |
| } |
| |
| /** |
| * @return the leash for this animation (only valid after the non app window surface animation |
| * has started). |
| */ |
| SurfaceControl getLeash() { |
| return mCapturedLeash; |
| } |
| |
| @Override |
| public void onAnimationCancelled(SurfaceControl animationLeash) { |
| ProtoLog.d(WM_DEBUG_REMOTE_ANIMATIONS, "onAnimationCancelled"); |
| } |
| |
| @Override |
| public void dump(PrintWriter pw, String prefix) { |
| pw.print(prefix); |
| pw.print("windowContainer="); |
| pw.println(mWindowContainer); |
| if (mTarget != null) { |
| pw.print(prefix); |
| pw.println("Target:"); |
| mTarget.dump(pw, prefix + " "); |
| } else { |
| pw.print(prefix); |
| pw.println("Target: null"); |
| } |
| } |
| |
| @Override |
| public void dumpDebug(ProtoOutputStream proto) { |
| final long token = proto.start(REMOTE); |
| if (mTarget != null) { |
| mTarget.dumpDebug(proto, TARGET); |
| } |
| proto.end(token); |
| } |
| } |