Files
Lawnchair/wmshell/src/com/android/wm/shell/transition/RecentsMixedTransition.java
T
2024-11-02 10:55:28 +08:00

228 lines
10 KiB
Java

/*
* Copyright (C) 2023 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.wm.shell.transition;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_UNOCCLUDING;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
import static com.android.wm.shell.transition.DefaultMixedHandler.handoverTransitionLeashes;
import static com.android.wm.shell.transition.MixedTransitionHelper.animateEnterPipFromSplit;
import static com.android.wm.shell.transition.MixedTransitionHelper.animateKeyguard;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.IBinder;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import android.window.WindowContainerTransaction;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.desktopmode.DesktopTasksController;
import com.android.wm.shell.keyguard.KeyguardTransitionHandler;
import com.android.wm.shell.pip.PipTransitionController;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentsTransitionHandler;
import com.android.wm.shell.splitscreen.StageCoordinator;
class RecentsMixedTransition extends DefaultMixedHandler.MixedTransition {
private final RecentsTransitionHandler mRecentsHandler;
private final DesktopTasksController mDesktopTasksController;
RecentsMixedTransition(int type, IBinder transition, Transitions player,
MixedTransitionHandler mixedHandler, PipTransitionController pipHandler,
StageCoordinator splitHandler, KeyguardTransitionHandler keyguardHandler,
RecentsTransitionHandler recentsHandler,
DesktopTasksController desktopTasksController) {
super(type, transition, player, mixedHandler, pipHandler, splitHandler, keyguardHandler);
mRecentsHandler = recentsHandler;
mDesktopTasksController = desktopTasksController;
mLeftoversHandler = mRecentsHandler;
}
@Override
boolean startAnimation(
@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
return switch (mType) {
case TYPE_RECENTS_DURING_DESKTOP ->
animateRecentsDuringDesktop(
info, startTransaction, finishTransaction, finishCallback);
case TYPE_RECENTS_DURING_KEYGUARD ->
animateRecentsDuringKeyguard(
info, startTransaction, finishTransaction, finishCallback);
case TYPE_RECENTS_DURING_SPLIT ->
animateRecentsDuringSplit(
info, startTransaction, finishTransaction, finishCallback);
default -> throw new IllegalStateException(
"Starting Recents mixed animation with unknown or illegal type: " + mType);
};
}
private boolean animateRecentsDuringDesktop(
@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Transition for Recents during"
+ " Desktop #%d", info.getDebugId());
if (mInfo == null) {
mInfo = info;
mFinishT = finishTransaction;
mFinishCB = finishCallback;
}
Transitions.TransitionFinishCallback finishCB = wct -> {
mInFlightSubAnimations--;
if (mInFlightSubAnimations == 0) {
finishCallback.onTransitionFinished(wct);
}
};
mInFlightSubAnimations++;
boolean consumed = mRecentsHandler.startAnimation(
mTransition, info, startTransaction, finishTransaction, finishCB);
if (!consumed) {
mInFlightSubAnimations--;
return false;
}
if (mDesktopTasksController != null) {
mDesktopTasksController.syncSurfaceState(info, finishTransaction);
return true;
}
return false;
}
private boolean animateRecentsDuringKeyguard(
@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for Recents during"
+ " Keyguard #%d", info.getDebugId());
if (mInfo == null) {
mInfo = info;
mFinishT = finishTransaction;
mFinishCB = finishCallback;
}
return startSubAnimation(mRecentsHandler, info, startTransaction, finishTransaction);
}
private boolean animateRecentsDuringSplit(
@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
ProtoLog.v(ShellProtoLogGroup.WM_SHELL_TRANSITIONS, "Mixed transition for Recents during"
+ " split screen #%d", info.getDebugId());
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
// Pip auto-entering info might be appended to recent transition like pressing
// home-key in 3-button navigation. This offers split handler the opportunity to
// handle split to pip animation.
if (mPipHandler.isEnteringPip(change, info.getType())
&& mSplitHandler.getSplitItemPosition(change.getLastParent())
!= SPLIT_POSITION_UNDEFINED) {
return animateEnterPipFromSplit(this, info, startTransaction, finishTransaction,
finishCallback, mPlayer, mMixedHandler, mPipHandler, mSplitHandler,
/*replacingPip*/ false);
}
}
// Split-screen is only interested in the recents transition finishing (and merging), so
// just wrap finish and start recents animation directly.
Transitions.TransitionFinishCallback finishCB = (wct) -> {
mInFlightSubAnimations = 0;
// If pair-to-pair switching, the post-recents clean-up isn't needed.
wct = wct != null ? wct : new WindowContainerTransaction();
if (mAnimType != ANIM_TYPE_PAIR_TO_PAIR) {
mSplitHandler.onRecentsInSplitAnimationFinish(wct, finishTransaction);
} else {
// notify pair-to-pair recents animation finish
mSplitHandler.onRecentsPairToPairAnimationFinish(wct);
}
mSplitHandler.onTransitionAnimationComplete();
finishCallback.onTransitionFinished(wct);
};
mInFlightSubAnimations = 1;
mSplitHandler.onRecentsInSplitAnimationStart(info);
final boolean handled = mLeftoversHandler.startAnimation(
mTransition, info, startTransaction, finishTransaction, finishCB);
if (!handled) {
mSplitHandler.onRecentsInSplitAnimationCanceled();
}
return handled;
}
@Override
void mergeAnimation(
@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
switch (mType) {
case TYPE_RECENTS_DURING_DESKTOP:
mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
return;
case TYPE_RECENTS_DURING_KEYGUARD:
if ((info.getFlags() & TRANSIT_FLAG_KEYGUARD_UNOCCLUDING) != 0) {
handoverTransitionLeashes(mInfo, info, t, mFinishT);
if (animateKeyguard(
this, info, t, mFinishT, mFinishCB, mKeyguardHandler, mPipHandler)) {
finishCallback.onTransitionFinished(null);
}
}
mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget,
finishCallback);
return;
case TYPE_RECENTS_DURING_SPLIT:
if (mSplitHandler.isPendingEnter(transition)) {
// Recents -> enter-split means that we are switching from one pair to
// another pair.
mAnimType = DefaultMixedHandler.MixedTransition.ANIM_TYPE_PAIR_TO_PAIR;
}
mLeftoversHandler.mergeAnimation(transition, info, t, mergeTarget, finishCallback);
return;
default:
throw new IllegalStateException("Playing a Recents mixed transition with unknown or"
+ " illegal type: " + mType);
}
}
@Override
void onTransitionConsumed(
@NonNull IBinder transition, boolean aborted,
@Nullable SurfaceControl.Transaction finishT) {
switch (mType) {
case TYPE_RECENTS_DURING_DESKTOP:
case TYPE_RECENTS_DURING_SPLIT:
case TYPE_RECENTS_DURING_KEYGUARD:
mLeftoversHandler.onTransitionConsumed(transition, aborted, finishT);
break;
default:
break;
}
if (mHasRequestToRemote) {
mPlayer.getRemoteTransitionHandler().onTransitionConsumed(transition, aborted, finishT);
}
}
}