228 lines
10 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|