Merge "PiP: Introduce PipTransitionState." into sc-v2-dev am: e9d456b056
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14687499 Change-Id: Idb0e54f74fed6d6421a4d3d9578fed9f67ddb94e
This commit is contained in:
@@ -107,38 +107,6 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
*/
|
||||
private static final int ONE_SHOT_ALPHA_ANIMATION_TIMEOUT_MS = 1000;
|
||||
|
||||
// Not a complete set of states but serves what we want right now.
|
||||
private enum State {
|
||||
UNDEFINED(0),
|
||||
TASK_APPEARED(1),
|
||||
ENTRY_SCHEDULED(2),
|
||||
ENTERING_PIP(3),
|
||||
ENTERED_PIP(4),
|
||||
EXITING_PIP(5);
|
||||
|
||||
private final int mStateValue;
|
||||
|
||||
State(int value) {
|
||||
mStateValue = value;
|
||||
}
|
||||
|
||||
private boolean isInPip() {
|
||||
return mStateValue >= TASK_APPEARED.mStateValue
|
||||
&& mStateValue != EXITING_PIP.mStateValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize request can be initiated in other component, ignore if we are no longer in PIP,
|
||||
* still waiting for animation or we're exiting from it.
|
||||
*
|
||||
* @return {@code true} if the resize request should be blocked/ignored.
|
||||
*/
|
||||
private boolean shouldBlockResizeRequest() {
|
||||
return mStateValue < ENTERING_PIP.mStateValue
|
||||
|| mStateValue == EXITING_PIP.mStateValue;
|
||||
}
|
||||
}
|
||||
|
||||
private final Context mContext;
|
||||
private final SyncTransactionQueue mSyncTransactionQueue;
|
||||
private final PipBoundsState mPipBoundsState;
|
||||
@@ -190,7 +158,8 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
}
|
||||
final boolean isExitPipDirection = isOutPipDirection(direction)
|
||||
|| isRemovePipDirection(direction);
|
||||
if (mState != State.EXITING_PIP || isExitPipDirection) {
|
||||
if (mPipTransitionState.getTransitionState() != PipTransitionState.EXITING_PIP
|
||||
|| isExitPipDirection) {
|
||||
// Finish resize as long as we're not exiting PIP, or, if we are, only if this is
|
||||
// the end of an exit PIP animation.
|
||||
// This is necessary in case there was a resize animation ongoing when exit PIP
|
||||
@@ -233,7 +202,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
private ActivityManager.RunningTaskInfo mDeferredTaskInfo;
|
||||
private WindowContainerToken mToken;
|
||||
private SurfaceControl mLeash;
|
||||
private State mState = State.UNDEFINED;
|
||||
private PipTransitionState mPipTransitionState;
|
||||
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
|
||||
private long mLastOneShotAlphaAnimationTime;
|
||||
private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
|
||||
@@ -278,6 +247,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
|
||||
public PipTaskOrganizer(Context context,
|
||||
@NonNull SyncTransactionQueue syncTransactionQueue,
|
||||
@NonNull PipTransitionState pipTransitionState,
|
||||
@NonNull PipBoundsState pipBoundsState,
|
||||
@NonNull PipBoundsAlgorithm boundsHandler,
|
||||
@NonNull PipMenuController pipMenuController,
|
||||
@@ -291,6 +261,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
mContext = context;
|
||||
mSyncTransactionQueue = syncTransactionQueue;
|
||||
mPipTransitionState = pipTransitionState;
|
||||
mPipBoundsState = pipBoundsState;
|
||||
mPipBoundsAlgorithm = boundsHandler;
|
||||
mPipMenuController = pipMenuController;
|
||||
@@ -326,14 +297,14 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
}
|
||||
|
||||
public boolean isInPip() {
|
||||
return mState.isInPip();
|
||||
return mPipTransitionState.isInPip();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the entry animation is waiting to be started.
|
||||
*/
|
||||
public boolean isEntryScheduled() {
|
||||
return mState == State.ENTRY_SCHEDULED;
|
||||
return mPipTransitionState.getTransitionState() == PipTransitionState.ENTRY_SCHEDULED;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -401,9 +372,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
* @param animationDurationMs duration in millisecond for the exiting PiP transition
|
||||
*/
|
||||
public void exitPip(int animationDurationMs) {
|
||||
if (!mState.isInPip() || mState == State.EXITING_PIP || mToken == null) {
|
||||
if (!mPipTransitionState.isInPip()
|
||||
|| mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP
|
||||
|| mToken == null) {
|
||||
Log.wtf(TAG, "Not allowed to exitPip in current state"
|
||||
+ " mState=" + mState + " mToken=" + mToken);
|
||||
+ " mState=" + mPipTransitionState.getTransitionState() + " mToken=" + mToken);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -427,7 +400,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
wct.setBoundsChangeTransaction(mToken, tx);
|
||||
// Set the exiting state first so if there is fixed rotation later, the running animation
|
||||
// won't be interrupted by alpha animation for existing PiP.
|
||||
mState = State.EXITING_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
|
||||
|
||||
if (Transitions.ENABLE_SHELL_TRANSITIONS) {
|
||||
mPipTransitionController.startTransition(destinationBounds, wct);
|
||||
@@ -470,9 +443,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
* Removes PiP immediately.
|
||||
*/
|
||||
public void removePip() {
|
||||
if (!mState.isInPip() || mToken == null) {
|
||||
if (!mPipTransitionState.isInPip() || mToken == null) {
|
||||
Log.wtf(TAG, "Not allowed to removePip in current state"
|
||||
+ " mState=" + mState + " mToken=" + mToken);
|
||||
+ " mState=" + mPipTransitionState.getTransitionState() + " mToken=" + mToken);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -486,7 +459,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
animator.setDuration(mExitAnimationDuration);
|
||||
animator.setInterpolator(Interpolators.ALPHA_OUT);
|
||||
animator.start();
|
||||
mState = State.EXITING_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
|
||||
}
|
||||
|
||||
private void removePipImmediately() {
|
||||
@@ -508,7 +481,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
Objects.requireNonNull(info, "Requires RunningTaskInfo");
|
||||
mTaskInfo = info;
|
||||
mToken = mTaskInfo.token;
|
||||
mState = State.TASK_APPEARED;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.TASK_APPEARED);
|
||||
mLeash = leash;
|
||||
mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
|
||||
setBoundsStateForEntry(mTaskInfo.topActivity, mPictureInPictureParams,
|
||||
@@ -562,7 +535,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
|
||||
sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration,
|
||||
null /* updateBoundsCallback */);
|
||||
mState = State.ENTERING_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
|
||||
} else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
||||
enterPipWithAlphaAnimation(destinationBounds, mEnterAnimationDuration);
|
||||
mOneShotAnimationType = ANIM_TYPE_BOUNDS;
|
||||
@@ -589,7 +562,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
|
||||
animateResizePip(currentBounds, destinationBounds, sourceHintRect,
|
||||
TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration, 0 /* startingAngle */);
|
||||
mState = State.ENTERING_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -614,7 +587,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mSurfaceControlTransactionFactory.getTransaction();
|
||||
tx.setAlpha(mLeash, 0f);
|
||||
tx.apply();
|
||||
mState = State.ENTRY_SCHEDULED;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTRY_SCHEDULED);
|
||||
applyEnterPipSyncTransaction(destinationBounds, () -> {
|
||||
mPipAnimationController
|
||||
.getAnimator(mTaskInfo, mLeash, destinationBounds, 0f, 1f)
|
||||
@@ -625,7 +598,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
.start();
|
||||
// mState is set right after the animation is kicked off to block any resize
|
||||
// requests such as offsetPip that may have been called prior to the transition.
|
||||
mState = State.ENTERING_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
|
||||
}, null /* boundsChangeTransaction */);
|
||||
}
|
||||
|
||||
@@ -672,7 +645,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
private void sendOnPipTransitionStarted(
|
||||
@PipAnimationController.TransitionDirection int direction) {
|
||||
if (direction == TRANSITION_DIRECTION_TO_PIP) {
|
||||
mState = State.ENTERING_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
|
||||
}
|
||||
mPipTransitionController.sendOnPipTransitionStarted(direction);
|
||||
}
|
||||
@@ -681,7 +654,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
void sendOnPipTransitionFinished(
|
||||
@PipAnimationController.TransitionDirection int direction) {
|
||||
if (direction == TRANSITION_DIRECTION_TO_PIP) {
|
||||
mState = State.ENTERED_PIP;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP);
|
||||
}
|
||||
mPipTransitionController.sendOnPipTransitionFinished(direction);
|
||||
// Apply the deferred RunningTaskInfo if applicable after all proper callbacks are sent.
|
||||
@@ -706,7 +679,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
*/
|
||||
@Override
|
||||
public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
|
||||
if (mState == State.UNDEFINED) {
|
||||
if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
|
||||
return;
|
||||
}
|
||||
final WindowContainerToken token = info.token;
|
||||
@@ -718,7 +691,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
clearWaitForFixedRotation();
|
||||
mInSwipePipToHomeTransition = false;
|
||||
mPictureInPictureParams = null;
|
||||
mState = State.UNDEFINED;
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED);
|
||||
// Re-set the PIP bounds to none.
|
||||
mPipBoundsState.setBounds(new Rect());
|
||||
mPipUiEventLoggerLogger.setTaskInfo(null);
|
||||
@@ -732,8 +705,10 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
@Override
|
||||
public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
|
||||
Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
|
||||
if (mState != State.ENTERED_PIP && mState != State.EXITING_PIP) {
|
||||
Log.d(TAG, "Defer onTaskInfoChange in current state: " + mState);
|
||||
if (mPipTransitionState.getTransitionState() != PipTransitionState.ENTERED_PIP
|
||||
&& mPipTransitionState.getTransitionState() != PipTransitionState.EXITING_PIP) {
|
||||
Log.d(TAG, "Defer onTaskInfoChange in current state: "
|
||||
+ mPipTransitionState.getTransitionState());
|
||||
// Defer applying PiP parameters if the task is entering PiP to avoid disturbing
|
||||
// the animation.
|
||||
mDeferredTaskInfo = info;
|
||||
@@ -766,7 +741,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mNextRotation = newRotation;
|
||||
mWaitForFixedRotation = true;
|
||||
|
||||
if (mState.isInPip()) {
|
||||
if (mPipTransitionState.isInPip()) {
|
||||
// Fade out the existing PiP to avoid jump cut during seamless rotation.
|
||||
fadeExistingPip(false /* show */);
|
||||
}
|
||||
@@ -777,7 +752,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
if (!mWaitForFixedRotation) {
|
||||
return;
|
||||
}
|
||||
if (mState == State.TASK_APPEARED) {
|
||||
if (mPipTransitionState.getTransitionState() == PipTransitionState.TASK_APPEARED) {
|
||||
if (mInSwipePipToHomeTransition) {
|
||||
onEndOfSwipePipToHomeTransition();
|
||||
} else {
|
||||
@@ -785,9 +760,11 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
enterPipWithAlphaAnimation(mPipBoundsAlgorithm.getEntryDestinationBounds(),
|
||||
mEnterAnimationDuration);
|
||||
}
|
||||
} else if (mState == State.ENTERED_PIP && mHasFadeOut) {
|
||||
} else if (mPipTransitionState.getTransitionState() == PipTransitionState.ENTERED_PIP
|
||||
&& mHasFadeOut) {
|
||||
fadeExistingPip(true /* show */);
|
||||
} else if (mState == State.ENTERING_PIP && mDeferredAnimEndTransaction != null) {
|
||||
} else if (mPipTransitionState.getTransitionState() == PipTransitionState.ENTERING_PIP
|
||||
&& mDeferredAnimEndTransaction != null) {
|
||||
final PipAnimationController.PipTransitionAnimator<?> animator =
|
||||
mPipAnimationController.getCurrentAnimator();
|
||||
final Rect destinationBounds = animator.getDestinationBounds();
|
||||
@@ -848,7 +825,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mPipAnimationController.getCurrentAnimator();
|
||||
if (animator == null || !animator.isRunning()
|
||||
|| animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
|
||||
final boolean rotatingPip = mState.isInPip() && fromRotation;
|
||||
final boolean rotatingPip = mPipTransitionState.isInPip() && fromRotation;
|
||||
if (rotatingPip && mWaitForFixedRotation && mHasFadeOut) {
|
||||
// The position will be used by fade-in animation when the fixed rotation is done.
|
||||
mPipBoundsState.setBounds(destinationBoundsOut);
|
||||
@@ -981,7 +958,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
Rect currentBounds, Rect destinationBounds, float startingAngle, Rect sourceHintRect,
|
||||
@PipAnimationController.TransitionDirection int direction, int durationMs,
|
||||
Consumer<Rect> updateBoundsCallback) {
|
||||
if (!mState.isInPip()) {
|
||||
if (!mPipTransitionState.isInPip()) {
|
||||
// TODO: tend to use shouldBlockResizeRequest here as well but need to consider
|
||||
// the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
|
||||
// container transaction callback and we want to set the mState immediately.
|
||||
@@ -1011,7 +988,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
|
||||
mSurfaceTransactionHelper
|
||||
.crop(tx, mLeash, toBounds)
|
||||
.round(tx, mLeash, mState.isInPip());
|
||||
.round(tx, mLeash, mPipTransitionState.isInPip());
|
||||
if (mPipMenuController.isMenuVisible()) {
|
||||
mPipMenuController.resizePipMenu(mLeash, tx, toBounds);
|
||||
} else {
|
||||
@@ -1089,7 +1066,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
public void scheduleFinishResizePip(Rect destinationBounds,
|
||||
@PipAnimationController.TransitionDirection int direction,
|
||||
Consumer<Rect> updateBoundsCallback) {
|
||||
if (mState.shouldBlockResizeRequest()) {
|
||||
if (mPipTransitionState.shouldBlockResizeRequest()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1106,7 +1083,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
mSurfaceTransactionHelper
|
||||
.crop(tx, mLeash, destinationBounds)
|
||||
.resetScale(tx, mLeash, destinationBounds)
|
||||
.round(tx, mLeash, mState.isInPip());
|
||||
.round(tx, mLeash, mPipTransitionState.isInPip());
|
||||
return tx;
|
||||
}
|
||||
|
||||
@@ -1115,7 +1092,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
*/
|
||||
public void scheduleOffsetPip(Rect originalBounds, int offset, int duration,
|
||||
Consumer<Rect> updateBoundsCallback) {
|
||||
if (mState.shouldBlockResizeRequest()) {
|
||||
if (mPipTransitionState.shouldBlockResizeRequest()) {
|
||||
return;
|
||||
}
|
||||
if (mWaitForFixedRotation) {
|
||||
@@ -1373,7 +1350,7 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
pw.println(innerPrefix + "mToken=" + mToken
|
||||
+ " binder=" + (mToken != null ? mToken.asBinder() : null));
|
||||
pw.println(innerPrefix + "mLeash=" + mLeash);
|
||||
pw.println(innerPrefix + "mState=" + mState);
|
||||
pw.println(innerPrefix + "mState=" + mPipTransitionState.getTransitionState());
|
||||
pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
|
||||
pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
|
||||
}
|
||||
|
||||
@@ -52,19 +52,23 @@ import com.android.wm.shell.transition.Transitions;
|
||||
*/
|
||||
public class PipTransition extends PipTransitionController {
|
||||
|
||||
private final PipTransitionState mPipTransitionState;
|
||||
private final int mEnterExitAnimationDuration;
|
||||
private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
|
||||
private Transitions.TransitionFinishCallback mFinishCallback;
|
||||
private Rect mExitDestinationBounds = new Rect();
|
||||
|
||||
public PipTransition(Context context,
|
||||
PipBoundsState pipBoundsState, PipMenuController pipMenuController,
|
||||
PipBoundsState pipBoundsState,
|
||||
PipTransitionState pipTransitionState,
|
||||
PipMenuController pipMenuController,
|
||||
PipBoundsAlgorithm pipBoundsAlgorithm,
|
||||
PipAnimationController pipAnimationController,
|
||||
Transitions transitions,
|
||||
@NonNull ShellTaskOrganizer shellTaskOrganizer) {
|
||||
super(pipBoundsState, pipMenuController, pipBoundsAlgorithm,
|
||||
pipAnimationController, transitions, shellTaskOrganizer);
|
||||
mPipTransitionState = pipTransitionState;
|
||||
mEnterExitAnimationDuration = context.getResources()
|
||||
.getInteger(R.integer.config_pipResizeAnimationDuration);
|
||||
}
|
||||
@@ -85,6 +89,7 @@ public class PipTransition extends PipTransitionController {
|
||||
if (info.getType() == TRANSIT_EXIT_PIP && info.getChanges().size() == 1) {
|
||||
final TransitionInfo.Change change = info.getChanges().get(0);
|
||||
mFinishCallback = finishCallback;
|
||||
startTransaction.apply();
|
||||
boolean success = startExpandAnimation(change.getTaskInfo(), change.getLeash(),
|
||||
new Rect(mExitDestinationBounds));
|
||||
mExitDestinationBounds.setEmpty();
|
||||
@@ -114,6 +119,7 @@ public class PipTransition extends PipTransitionController {
|
||||
startTransaction.setAlpha(wallpaper.getLeash(), 1.f);
|
||||
}
|
||||
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
|
||||
mFinishCallback = finishCallback;
|
||||
return startEnterAnimation(enterPip.getTaskInfo(), enterPip.getLeash(),
|
||||
startTransaction, finishTransaction);
|
||||
@@ -130,6 +136,9 @@ public class PipTransition extends PipTransitionController {
|
||||
public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds,
|
||||
@PipAnimationController.TransitionDirection int direction,
|
||||
SurfaceControl.Transaction tx) {
|
||||
if (isInPipDirection(direction)) {
|
||||
mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP);
|
||||
}
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
prepareFinishResizeTransaction(taskInfo, destinationBounds,
|
||||
direction, tx, wct);
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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.wm.shell.pip;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Used to keep track of PiP leash state as it appears and animates by {@link PipTaskOrganizer} and
|
||||
* {@link PipTransition}.
|
||||
*/
|
||||
public class PipTransitionState {
|
||||
|
||||
public static final int UNDEFINED = 0;
|
||||
public static final int TASK_APPEARED = 1;
|
||||
public static final int ENTRY_SCHEDULED = 2;
|
||||
public static final int ENTERING_PIP = 3;
|
||||
public static final int ENTERED_PIP = 4;
|
||||
public static final int EXITING_PIP = 5;
|
||||
|
||||
// Not a complete set of states but serves what we want right now.
|
||||
@IntDef(prefix = { "TRANSITION_STATE_" }, value = {
|
||||
UNDEFINED,
|
||||
TASK_APPEARED,
|
||||
ENTRY_SCHEDULED,
|
||||
ENTERING_PIP,
|
||||
ENTERED_PIP,
|
||||
EXITING_PIP
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface TransitionState {}
|
||||
|
||||
private @TransitionState int mState;
|
||||
|
||||
public PipTransitionState() {
|
||||
mState = UNDEFINED;
|
||||
}
|
||||
|
||||
public void setTransitionState(@TransitionState int state) {
|
||||
mState = state;
|
||||
}
|
||||
|
||||
public @TransitionState int getTransitionState() {
|
||||
return mState;
|
||||
}
|
||||
|
||||
public boolean isInPip() {
|
||||
return mState >= TASK_APPEARED
|
||||
&& mState != EXITING_PIP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize request can be initiated in other component, ignore if we are no longer in PIP,
|
||||
* still waiting for animation or we're exiting from it.
|
||||
*
|
||||
* @return {@code true} if the resize request should be blocked/ignored.
|
||||
*/
|
||||
public boolean shouldBlockResizeRequest() {
|
||||
return mState < ENTERING_PIP
|
||||
|| mState == EXITING_PIP;
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,7 @@ public class PipTaskOrganizerTest extends ShellTestCase {
|
||||
@Mock private ShellTaskOrganizer mMockShellTaskOrganizer;
|
||||
private TestShellExecutor mMainExecutor;
|
||||
private PipBoundsState mPipBoundsState;
|
||||
private PipTransitionState mPipTransitionState;
|
||||
private PipBoundsAlgorithm mPipBoundsAlgorithm;
|
||||
|
||||
private ComponentName mComponent1;
|
||||
@@ -90,11 +91,12 @@ public class PipTaskOrganizerTest extends ShellTestCase {
|
||||
mComponent1 = new ComponentName(mContext, "component1");
|
||||
mComponent2 = new ComponentName(mContext, "component2");
|
||||
mPipBoundsState = new PipBoundsState(mContext);
|
||||
mPipTransitionState = new PipTransitionState();
|
||||
mPipBoundsAlgorithm = new PipBoundsAlgorithm(mContext, mPipBoundsState,
|
||||
new PipSnapAlgorithm());
|
||||
mMainExecutor = new TestShellExecutor();
|
||||
mSpiedPipTaskOrganizer = spy(new PipTaskOrganizer(mContext,
|
||||
mMockSyncTransactionQueue, mPipBoundsState,
|
||||
mMockSyncTransactionQueue, mPipTransitionState, mPipBoundsState,
|
||||
mPipBoundsAlgorithm, mMockPhonePipMenuController,
|
||||
mMockPipAnimationController, mMockPipSurfaceTransactionHelper,
|
||||
mMockPipTransitionController, mMockOptionalSplitScreen, mMockDisplayController,
|
||||
|
||||
@@ -38,6 +38,7 @@ import com.android.wm.shell.pip.PipSnapAlgorithm;
|
||||
import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
|
||||
import com.android.wm.shell.pip.PipTaskOrganizer;
|
||||
import com.android.wm.shell.pip.PipTransitionController;
|
||||
import com.android.wm.shell.pip.PipTransitionState;
|
||||
import com.android.wm.shell.pip.PipUiEventLogger;
|
||||
import com.android.wm.shell.pip.tv.TvPipController;
|
||||
import com.android.wm.shell.pip.tv.TvPipMenuController;
|
||||
@@ -142,12 +143,19 @@ public abstract class TvPipModule {
|
||||
return new PipAnimationController(pipSurfaceTransactionHelper);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static PipTransitionState providePipTransitionState() {
|
||||
return new PipTransitionState();
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static PipTaskOrganizer providePipTaskOrganizer(Context context,
|
||||
TvPipMenuController tvPipMenuController,
|
||||
SyncTransactionQueue syncTransactionQueue,
|
||||
PipBoundsState pipBoundsState,
|
||||
PipTransitionState pipTransitionState,
|
||||
PipBoundsAlgorithm pipBoundsAlgorithm,
|
||||
PipAnimationController pipAnimationController,
|
||||
PipTransitionController pipTransitionController,
|
||||
@@ -157,7 +165,7 @@ public abstract class TvPipModule {
|
||||
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new PipTaskOrganizer(context,
|
||||
syncTransactionQueue, pipBoundsState, pipBoundsAlgorithm,
|
||||
syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm,
|
||||
tvPipMenuController, pipAnimationController, pipSurfaceTransactionHelper,
|
||||
pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger,
|
||||
shellTaskOrganizer, mainExecutor);
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
|
||||
import com.android.wm.shell.pip.PipTaskOrganizer;
|
||||
import com.android.wm.shell.pip.PipTransition;
|
||||
import com.android.wm.shell.pip.PipTransitionController;
|
||||
import com.android.wm.shell.pip.PipTransitionState;
|
||||
import com.android.wm.shell.pip.PipUiEventLogger;
|
||||
import com.android.wm.shell.pip.phone.PhonePipMenuController;
|
||||
import com.android.wm.shell.pip.phone.PipAppOpsListener;
|
||||
@@ -182,10 +183,17 @@ public class WMShellModule {
|
||||
floatingContentCoordinator, pipUiEventLogger, mainExecutor);
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static PipTransitionState providePipTransitionState() {
|
||||
return new PipTransitionState();
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static PipTaskOrganizer providePipTaskOrganizer(Context context,
|
||||
SyncTransactionQueue syncTransactionQueue,
|
||||
PipTransitionState pipTransitionState,
|
||||
PipBoundsState pipBoundsState,
|
||||
PipBoundsAlgorithm pipBoundsAlgorithm,
|
||||
PhonePipMenuController menuPhoneController,
|
||||
@@ -197,7 +205,7 @@ public class WMShellModule {
|
||||
PipUiEventLogger pipUiEventLogger, ShellTaskOrganizer shellTaskOrganizer,
|
||||
@ShellMainThread ShellExecutor mainExecutor) {
|
||||
return new PipTaskOrganizer(context,
|
||||
syncTransactionQueue, pipBoundsState, pipBoundsAlgorithm,
|
||||
syncTransactionQueue, pipTransitionState, pipBoundsState, pipBoundsAlgorithm,
|
||||
menuPhoneController, pipAnimationController, pipSurfaceTransactionHelper,
|
||||
pipTransitionController, splitScreenOptional, displayController, pipUiEventLogger,
|
||||
shellTaskOrganizer, mainExecutor);
|
||||
@@ -215,8 +223,9 @@ public class WMShellModule {
|
||||
static PipTransitionController providePipTransitionController(Context context,
|
||||
Transitions transitions, ShellTaskOrganizer shellTaskOrganizer,
|
||||
PipAnimationController pipAnimationController, PipBoundsAlgorithm pipBoundsAlgorithm,
|
||||
PipBoundsState pipBoundsState, PhonePipMenuController pipMenuController) {
|
||||
return new PipTransition(context, pipBoundsState, pipMenuController,
|
||||
PipBoundsState pipBoundsState, PipTransitionState pipTransitionState,
|
||||
PhonePipMenuController pipMenuController) {
|
||||
return new PipTransition(context, pipBoundsState, pipTransitionState, pipMenuController,
|
||||
pipBoundsAlgorithm, pipAnimationController, transitions, shellTaskOrganizer);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user