Use mobile code for TV Shell Transitions.
- Uses alpha instead of bounds animation on TV during PiP entry - Attaches the menu earlier to make sure the PiP immediately appears in the right position as the menu affects the position. Bug: 271098548 Bug: 228071323 Test: manual - PiP should fade in instead of being scaled from fullscreen to the PiP size, PiP should not appear low and then move up. Change-Id: I51b6deea3d0e2f2e7166e9df8c98685d6aee82a3
This commit is contained in:
@@ -157,14 +157,21 @@ public abstract class TvPipModule {
|
||||
@WMSingleton
|
||||
@Provides
|
||||
static PipTransitionController provideTvPipTransition(
|
||||
Context context,
|
||||
ShellInit shellInit,
|
||||
ShellTaskOrganizer shellTaskOrganizer,
|
||||
Transitions transitions,
|
||||
PipAnimationController pipAnimationController,
|
||||
TvPipBoundsState tvPipBoundsState,
|
||||
PipDisplayLayoutState pipDisplayLayoutState,
|
||||
PipTransitionState pipTransitionState,
|
||||
TvPipMenuController pipMenuController,
|
||||
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
|
||||
TvPipBoundsState tvPipBoundsState, TvPipMenuController pipMenuController) {
|
||||
return new TvPipTransition(shellInit, shellTaskOrganizer, transitions, tvPipBoundsState,
|
||||
pipMenuController, tvPipBoundsAlgorithm, pipAnimationController);
|
||||
PipAnimationController pipAnimationController,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper) {
|
||||
return new TvPipTransition(context, shellInit, shellTaskOrganizer, transitions,
|
||||
tvPipBoundsState, pipDisplayLayoutState, pipTransitionState, pipMenuController,
|
||||
tvPipBoundsAlgorithm, pipAnimationController, pipSurfaceTransactionHelper,
|
||||
Optional.empty());
|
||||
}
|
||||
|
||||
@WMSingleton
|
||||
|
||||
@@ -415,6 +415,26 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override if the PiP should always use a fade-in animation during PiP entry.
|
||||
*
|
||||
* @return true if the mOneShotAnimationType should always be
|
||||
* {@link PipAnimationController#ANIM_TYPE_ALPHA}.
|
||||
*/
|
||||
protected boolean shouldAlwaysFadeIn() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the menu should get attached as early as possible when entering PiP.
|
||||
*
|
||||
* @return whether the menu should be attached before
|
||||
* {@link PipBoundsAlgorithm#getEntryDestinationBounds()} is called.
|
||||
*/
|
||||
protected boolean shouldAttachMenuEarly() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback when Launcher starts swipe-pip-to-home operation.
|
||||
* @return {@link Rect} for destination bounds.
|
||||
@@ -709,17 +729,26 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldAlwaysFadeIn()) {
|
||||
mOneShotAnimationType = ANIM_TYPE_ALPHA;
|
||||
}
|
||||
|
||||
if (mWaitForFixedRotation) {
|
||||
onTaskAppearedWithFixedRotation();
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldAttachMenuEarly()) {
|
||||
mPipMenuController.attach(mLeash);
|
||||
}
|
||||
final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
|
||||
Objects.requireNonNull(destinationBounds, "Missing destination bounds");
|
||||
final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
|
||||
|
||||
if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
|
||||
mPipMenuController.attach(mLeash);
|
||||
if (!shouldAttachMenuEarly()) {
|
||||
mPipMenuController.attach(mLeash);
|
||||
}
|
||||
final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
|
||||
info.pictureInPictureParams, currentBounds);
|
||||
scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
|
||||
@@ -834,7 +863,9 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
|
||||
@Nullable SurfaceControl.Transaction boundsChangeTransaction) {
|
||||
// PiP menu is attached late in the process here to avoid any artifacts on the leash
|
||||
// caused by addShellRoot when in gesture navigation mode.
|
||||
mPipMenuController.attach(mLeash);
|
||||
if (!shouldAttachMenuEarly()) {
|
||||
mPipMenuController.attach(mLeash);
|
||||
}
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
|
||||
wct.setBounds(mToken, destinationBounds);
|
||||
|
||||
@@ -272,6 +272,8 @@ public class PipTransition extends PipTransitionController {
|
||||
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||
@NonNull TransitionRequestInfo request) {
|
||||
if (requestHasPipEnter(request)) {
|
||||
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
|
||||
"%s: handle PiP enter request", TAG);
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
augmentRequest(transition, request, wct);
|
||||
return wct;
|
||||
@@ -731,6 +733,11 @@ public class PipTransition extends PipTransitionController {
|
||||
|
||||
setBoundsStateForEntry(taskInfo.topActivity, taskInfo.pictureInPictureParams,
|
||||
taskInfo.topActivityInfo);
|
||||
|
||||
if (mPipOrganizer.shouldAttachMenuEarly()) {
|
||||
mPipMenuController.attach(leash);
|
||||
}
|
||||
|
||||
final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
|
||||
final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds();
|
||||
int rotationDelta = deltaRotation(startRotation, endRotation);
|
||||
@@ -745,7 +752,10 @@ public class PipTransition extends PipTransitionController {
|
||||
mSurfaceTransactionHelper
|
||||
.crop(finishTransaction, leash, destinationBounds)
|
||||
.round(finishTransaction, leash, true /* applyCornerRadius */);
|
||||
mTransitions.getMainExecutor().executeDelayed(() -> mPipMenuController.attach(leash), 0);
|
||||
if (!mPipOrganizer.shouldAttachMenuEarly()) {
|
||||
mTransitions.getMainExecutor().executeDelayed(
|
||||
() -> mPipMenuController.attach(leash), 0);
|
||||
}
|
||||
|
||||
if (taskInfo.pictureInPictureParams != null
|
||||
&& taskInfo.pictureInPictureParams.isAutoEnterEnabled()
|
||||
@@ -785,6 +795,11 @@ public class PipTransition extends PipTransitionController {
|
||||
tmpTransform.postRotate(rotationDelta);
|
||||
startTransaction.setMatrix(leash, tmpTransform, new float[9]);
|
||||
}
|
||||
|
||||
if (mPipOrganizer.shouldAlwaysFadeIn()) {
|
||||
mOneShotAnimationType = ANIM_TYPE_ALPHA;
|
||||
}
|
||||
|
||||
if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
|
||||
startTransaction.setAlpha(leash, 0f);
|
||||
}
|
||||
|
||||
@@ -446,7 +446,7 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
|
||||
"%s: PiP has already been closed by custom close action", TAG);
|
||||
return;
|
||||
}
|
||||
removeTask(mPinnedTaskId);
|
||||
mPipTaskOrganizer.removePip();
|
||||
onPipDisappeared();
|
||||
}
|
||||
|
||||
@@ -673,17 +673,6 @@ public class TvPipController implements PipTransitionController.PipTransitionCal
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeTask(int taskId) {
|
||||
ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
|
||||
"%s: removeTask(), taskId=%d", TAG, taskId);
|
||||
try {
|
||||
ActivityTaskManager.getService().removeTask(taskId);
|
||||
} catch (Exception e) {
|
||||
ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
|
||||
"%s: Atm.removeTask() failed, %s", TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
private static String stateToName(@State int state) {
|
||||
switch (state) {
|
||||
case STATE_NO_PIP:
|
||||
|
||||
@@ -85,4 +85,17 @@ public class TvPipTaskOrganizer extends PipTaskOrganizer {
|
||||
mPipParamsChangedForwarder.notifySubtitleChanged(params.getSubtitle());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Override for TV since the menu bounds affect the PiP location. Additionally, we want to
|
||||
* ensure that menu is shown immediately since it should always be visible on TV as it creates
|
||||
* a border with rounded corners around the PiP.
|
||||
*/
|
||||
protected boolean shouldAttachMenuEarly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected boolean shouldAlwaysFadeIn() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,60 +16,43 @@
|
||||
|
||||
package com.android.wm.shell.pip.tv;
|
||||
|
||||
import android.app.TaskInfo;
|
||||
import android.graphics.Rect;
|
||||
import android.os.IBinder;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.TransitionInfo;
|
||||
import android.window.TransitionRequestInfo;
|
||||
import android.window.WindowContainerTransaction;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.wm.shell.ShellTaskOrganizer;
|
||||
import com.android.wm.shell.pip.PipAnimationController;
|
||||
import com.android.wm.shell.pip.PipBoundsState;
|
||||
import com.android.wm.shell.pip.PipMenuController;
|
||||
import com.android.wm.shell.pip.PipTransitionController;
|
||||
import com.android.wm.shell.pip.PipDisplayLayoutState;
|
||||
import com.android.wm.shell.pip.PipSurfaceTransactionHelper;
|
||||
import com.android.wm.shell.pip.PipTransition;
|
||||
import com.android.wm.shell.pip.PipTransitionState;
|
||||
import com.android.wm.shell.splitscreen.SplitScreenController;
|
||||
import com.android.wm.shell.sysui.ShellInit;
|
||||
import com.android.wm.shell.transition.Transitions;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* PiP Transition for TV.
|
||||
* TODO: Implement animation once TV is using Transitions.
|
||||
*/
|
||||
public class TvPipTransition extends PipTransitionController {
|
||||
public TvPipTransition(
|
||||
public class TvPipTransition extends PipTransition {
|
||||
|
||||
public TvPipTransition(Context context,
|
||||
@NonNull ShellInit shellInit,
|
||||
@NonNull ShellTaskOrganizer shellTaskOrganizer,
|
||||
@NonNull Transitions transitions,
|
||||
PipBoundsState pipBoundsState,
|
||||
PipMenuController pipMenuController,
|
||||
TvPipBoundsState tvPipBoundsState,
|
||||
PipDisplayLayoutState pipDisplayLayoutState,
|
||||
PipTransitionState pipTransitionState,
|
||||
TvPipMenuController tvPipMenuController,
|
||||
TvPipBoundsAlgorithm tvPipBoundsAlgorithm,
|
||||
PipAnimationController pipAnimationController) {
|
||||
super(shellInit, shellTaskOrganizer, transitions, pipBoundsState, pipMenuController,
|
||||
tvPipBoundsAlgorithm, pipAnimationController);
|
||||
PipAnimationController pipAnimationController,
|
||||
PipSurfaceTransactionHelper pipSurfaceTransactionHelper,
|
||||
Optional<SplitScreenController> splitScreenOptional) {
|
||||
super(context, shellInit, shellTaskOrganizer, transitions, tvPipBoundsState,
|
||||
pipDisplayLayoutState, pipTransitionState, tvPipMenuController,
|
||||
tvPipBoundsAlgorithm, pipAnimationController, pipSurfaceTransactionHelper,
|
||||
splitScreenOptional);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds, int direction,
|
||||
SurfaceControl.Transaction tx) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
|
||||
@NonNull SurfaceControl.Transaction startTransaction,
|
||||
@android.annotation.NonNull SurfaceControl.Transaction finishTransaction,
|
||||
@NonNull Transitions.TransitionFinishCallback finishCallback) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WindowContainerTransaction handleRequest(@NonNull IBinder transition,
|
||||
@NonNull TransitionRequestInfo request) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user