From 3bec45cdee23c85dbb08f88bf3a6d02a4afc6db1 Mon Sep 17 00:00:00 2001 From: Gustav Sennton Date: Wed, 18 Dec 2024 09:39:52 +0000 Subject: [PATCH] Override desktop tasks corner radius during recents transition Set the corner radius of desktop task surfaces to 0 during recents transitions so that corner radius doesn't interfere with the surface bounds and corner radius applied to the RemoteAnimationTarget leashes. Bug: 378657004 Test: manual Flag: com.android.window.flags.enable_desktop_recents_transitions_corners_bugfix Change-Id: Ia653ace883cabfcd573ac138cb22affd96f7f229 --- .../android/quickstep/AbsSwipeUpHandler.java | 7 ++-- .../com/android/quickstep/GestureState.java | 3 +- .../quickstep/OverviewCommandHelper.kt | 2 + .../quickstep/RecentsAnimationCallbacks.java | 10 +++-- .../android/quickstep/RemoteTargetGluer.java | 5 ++- .../com/android/quickstep/SystemUiProxy.kt | 3 ++ .../quickstep/TaskAnimationManager.java | 8 +++- .../com/android/quickstep/TaskViewUtils.java | 3 +- .../window/RecentsWindowSwipeHandler.java | 5 ++- .../DeviceLockedInputConsumer.java | 3 +- .../ProgressDelegateInputConsumer.java | 3 +- .../util/SplitSelectStateController.java | 6 +-- .../SplitWithKeyboardShortcutController.java | 3 +- .../quickstep/util/TransformParams.java | 37 +++++++++++++++++++ .../android/quickstep/views/RecentsView.java | 3 +- .../quickstep/AbsSwipeUpHandlerTestCase.java | 2 +- 16 files changed, 81 insertions(+), 22 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index 03394efd6e..97e4fede7c 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -98,6 +98,7 @@ import android.view.animation.Interpolator; import android.widget.Toast; import android.window.DesktopModeFlags; import android.window.PictureInPictureSurfaceTransaction; +import android.window.TransitionInfo; import android.window.WindowAnimationState; import androidx.annotation.NonNull; @@ -954,10 +955,10 @@ public abstract class AbsSwipeUpHandler< @Override public void onRecentsAnimationStart(RecentsAnimationController controller, - RecentsAnimationTargets targets) { - super.onRecentsAnimationStart(controller, targets); + RecentsAnimationTargets targets, TransitionInfo transitionInfo) { + super.onRecentsAnimationStart(controller, targets, transitionInfo); if (targets.hasDesktopTasks(mContext)) { - mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets); + mRemoteTargetHandles = mTargetGluer.assignTargetsForDesktop(targets, transitionInfo); } else { int untrimmedAppCount = mRemoteTargetHandles.length; mRemoteTargetHandles = mTargetGluer.assignTargetsForSplitScreen(targets); diff --git a/quickstep/src/com/android/quickstep/GestureState.java b/quickstep/src/com/android/quickstep/GestureState.java index cfbcf0ad47..e0fa77a58d 100644 --- a/quickstep/src/com/android/quickstep/GestureState.java +++ b/quickstep/src/com/android/quickstep/GestureState.java @@ -33,6 +33,7 @@ import android.content.Intent; import android.os.SystemClock; import android.view.MotionEvent; import android.view.RemoteAnimationTarget; +import android.window.TransitionInfo; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -491,7 +492,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL @Override public void onRecentsAnimationStart(RecentsAnimationController controller, - RecentsAnimationTargets targets) { + RecentsAnimationTargets targets, TransitionInfo info) { mStateCallback.setState(STATE_RECENTS_ANIMATION_STARTED); } diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt index 089706f48e..66f307cd32 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt @@ -23,6 +23,7 @@ import android.os.SystemClock import android.os.Trace import android.util.Log import android.view.View +import android.window.TransitionInfo import androidx.annotation.BinderThread import androidx.annotation.UiThread import androidx.annotation.VisibleForTesting @@ -369,6 +370,7 @@ constructor( override fun onRecentsAnimationStart( controller: RecentsAnimationController, targets: RecentsAnimationTargets, + transitionInfo: TransitionInfo, ) { Log.d(TAG, "recents animation started: $command") updateRecentsViewFocus(command) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index 8fc1a785ad..87bf81c218 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -26,6 +26,7 @@ import android.graphics.Rect; import android.os.Bundle; import android.util.ArraySet; import android.view.RemoteAnimationTarget; +import android.window.TransitionInfo; import androidx.annotation.BinderThread; import androidx.annotation.NonNull; @@ -93,7 +94,7 @@ public class RecentsAnimationCallbacks implements RemoteAnimationTarget[] appTargets, Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras) { onAnimationStart(controller, appTargets, new RemoteAnimationTarget[0], - homeContentInsets, minimizedHomeBounds, extras); + homeContentInsets, minimizedHomeBounds, extras, /* transitionInfo= */ null); } // Called only in R+ platform @@ -101,7 +102,8 @@ public class RecentsAnimationCallbacks implements public final void onAnimationStart(RecentsAnimationControllerCompat animationController, RemoteAnimationTarget[] appTargets, RemoteAnimationTarget[] wallpaperTargets, - Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras) { + Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras, + TransitionInfo transitionInfo) { long appCount = Arrays.stream(appTargets) .filter(app -> app.mode == MODE_CLOSING) .count(); @@ -141,7 +143,7 @@ public class RecentsAnimationCallbacks implements Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> { ActiveGestureProtoLogProxy.logOnRecentsAnimationStart(targets.apps.length); for (RecentsAnimationListener listener : getListeners()) { - listener.onRecentsAnimationStart(mController, targets); + listener.onRecentsAnimationStart(mController, targets, transitionInfo); } }); } @@ -205,7 +207,7 @@ public class RecentsAnimationCallbacks implements */ public interface RecentsAnimationListener { default void onRecentsAnimationStart(RecentsAnimationController controller, - RecentsAnimationTargets targets) {} + RecentsAnimationTargets targets, TransitionInfo transitionInfo) {} /** * Callback from the system when the recents animation is canceled. {@param thumbnailData} diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java index 89337e5cea..8edbacb32d 100644 --- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java +++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java @@ -24,6 +24,7 @@ import android.content.Context; import android.graphics.Rect; import android.util.Log; import android.view.RemoteAnimationTarget; +import android.window.TransitionInfo; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -213,7 +214,8 @@ public class RemoteTargetGluer { * Similar to {@link #assignTargets(RemoteAnimationTargets)}, except this creates distinct * transform params per app in {@code targets.apps} list. */ - public RemoteTargetHandle[] assignTargetsForDesktop(RemoteAnimationTargets targets) { + public RemoteTargetHandle[] assignTargetsForDesktop( + RemoteAnimationTargets targets, TransitionInfo transitionInfo) { resizeRemoteTargetHandles(targets); for (int i = 0; i < mRemoteTargetHandles.length; i++) { @@ -222,6 +224,7 @@ public class RemoteTargetGluer { .filter(target -> target.taskId != primaryTaskTarget.taskId).toList(); mRemoteTargetHandles[i].mTransformParams.setTargetSet( createRemoteAnimationTargetsForTarget(targets, excludeTargets)); + mRemoteTargetHandles[i].mTransformParams.setTransitionInfo(transitionInfo); mRemoteTargetHandles[i].mTaskViewSimulator.setPreview(primaryTaskTarget, null); } return mRemoteTargetHandles; diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.kt b/quickstep/src/com/android/quickstep/SystemUiProxy.kt index 75694af97d..a7405a0bae 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.kt +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.kt @@ -45,6 +45,7 @@ import android.window.IOnBackInvokedCallback import android.window.RemoteTransition import android.window.TaskSnapshot import android.window.TransitionFilter +import android.window.TransitionInfo import androidx.annotation.MainThread import androidx.annotation.VisibleForTesting import androidx.annotation.WorkerThread @@ -1174,6 +1175,7 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context: homeContentInsets: Rect?, minimizedHomeBounds: Rect?, extras: Bundle?, + transitionInfo: TransitionInfo?, ) = listener.onAnimationStart( RecentsAnimationControllerCompat(controller), @@ -1186,6 +1188,7 @@ class SystemUiProxy @Inject constructor(@ApplicationContext private val context: // https://developer.android.com/guide/components/aidl#Bundles classLoader = SplitBounds::class.java.classLoader }, + transitionInfo, ) override fun onAnimationCanceled(taskIds: IntArray?, taskSnapshots: Array?) = diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index e0d4dddc87..cea79317de 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -36,6 +36,7 @@ import android.content.Intent; import android.os.SystemProperties; import android.util.Log; import android.view.RemoteAnimationTarget; +import android.window.TransitionInfo; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -69,6 +70,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn private RecentsAnimationController mController; private RecentsAnimationCallbacks mCallbacks; private RecentsAnimationTargets mTargets; + private TransitionInfo mTransitionInfo; private RecentsAnimationDeviceState mDeviceState; // Temporary until we can hook into gesture state events @@ -166,7 +168,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() { @Override public void onRecentsAnimationStart(RecentsAnimationController controller, - RecentsAnimationTargets targets) { + RecentsAnimationTargets targets, TransitionInfo transitionInfo) { if (enableHandleDelayedGestureCallbacks() && mRecentsAnimationStartPending) { ActiveGestureProtoLogProxy.logStartRecentsAnimationCallback( "onRecentsAnimationStart"); @@ -180,6 +182,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn } mController = controller; mTargets = targets; + mTransitionInfo = transitionInfo; // TODO(b/236226779): We can probably get away w/ setting mLastAppearedTaskTargets // to all appeared targets directly vs just looking at running ones int[] runningTaskIds = mLastGestureState.getRunningTaskIds(targets.apps.length > 1); @@ -448,7 +451,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn public void notifyRecentsAnimationState( RecentsAnimationCallbacks.RecentsAnimationListener listener) { if (isRecentsAnimationRunning()) { - listener.onRecentsAnimationStart(mController, mTargets); + listener.onRecentsAnimationStart(mController, mTargets, mTransitionInfo); } // TODO: Do we actually need to report canceled/finished? } @@ -488,6 +491,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mController = null; mCallbacks = null; mTargets = null; + mTransitionInfo = null; mLastGestureState = null; mLastAppearedTaskTargets = null; } diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index dec36cf8ca..3e90374a9d 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -189,7 +189,8 @@ public final class TaskViewUtils { RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(), recentsView.getSizeStrategy(), targets, forDesktop); if (forDesktop) { - remoteTargetHandles = gluer.assignTargetsForDesktop(targets); + remoteTargetHandles = + gluer.assignTargetsForDesktop(targets, /* transitionInfo=*/ null); } else if (v.containsMultipleTasks()) { remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, ((GroupedTaskView) v).getSplitBoundsConfig()); diff --git a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java index afc88792d6..5ba80b5638 100644 --- a/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java +++ b/quickstep/src/com/android/quickstep/fallback/window/RecentsWindowSwipeHandler.java @@ -49,6 +49,7 @@ import android.view.Surface; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.animation.Interpolator; +import android.window.TransitionInfo; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -126,8 +127,8 @@ public class RecentsWindowSwipeHandler extends AbsSwipeUpHandler { @@ -708,7 +708,7 @@ public class SplitSelectStateController { null /* nonApps */, mStateManager, mDepthController, - info, t, () -> { + transitionInfo, t, () -> { finishAdapter.run(); cleanup(true /*success*/); }, @@ -920,7 +920,7 @@ public class SplitSelectStateController { @Override public void onRecentsAnimationStart(RecentsAnimationController controller, - RecentsAnimationTargets targets) { + RecentsAnimationTargets targets, TransitionInfo transitionInfo) { StatsLogManager.LauncherEvent launcherDesktopSplitEvent = mSplitPosition == STAGE_POSITION_BOTTOM_OR_RIGHT ? LAUNCHER_DESKTOP_MODE_SPLIT_RIGHT_BOTTOM : diff --git a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java index 0ba408399e..107f5a3fca 100644 --- a/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java +++ b/quickstep/src/com/android/quickstep/util/SplitWithKeyboardShortcutController.java @@ -30,6 +30,7 @@ import android.app.ActivityManager; import android.app.ActivityOptions; import android.graphics.Rect; import android.graphics.RectF; +import android.window.TransitionInfo; import androidx.annotation.BinderThread; @@ -122,7 +123,7 @@ public class SplitWithKeyboardShortcutController { @Override public void onRecentsAnimationStart(RecentsAnimationController controller, - RecentsAnimationTargets targets) { + RecentsAnimationTargets targets, TransitionInfo transitionInfo) { mController.setInitialTaskSelect(mRunningTaskInfo, mLeftOrTop ? STAGE_POSITION_TOP_OR_LEFT : STAGE_POSITION_BOTTOM_OR_RIGHT, null /* itemInfo */, diff --git a/quickstep/src/com/android/quickstep/util/TransformParams.java b/quickstep/src/com/android/quickstep/util/TransformParams.java index 401eccc3bd..bb888189d4 100644 --- a/quickstep/src/com/android/quickstep/util/TransformParams.java +++ b/quickstep/src/com/android/quickstep/util/TransformParams.java @@ -19,9 +19,12 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import android.util.FloatProperty; import android.view.RemoteAnimationTarget; +import android.view.SurfaceControl; +import android.window.TransitionInfo; import com.android.quickstep.RemoteAnimationTargets; import com.android.quickstep.util.SurfaceTransaction.SurfaceProperties; +import com.android.window.flags.Flags; public class TransformParams { @@ -56,6 +59,7 @@ public class TransformParams { private float mTargetAlpha; private float mCornerRadius; private RemoteAnimationTargets mTargetSet; + private TransitionInfo mTransitionInfo; private SurfaceTransactionApplier mSyncTransactionApplier; private BuilderProxy mHomeBuilderProxy = BuilderProxy.ALWAYS_VISIBLE; @@ -106,6 +110,14 @@ public class TransformParams { return this; } + /** + * Provides the {@code TransitionInfo} of the transition that this transformation stems from. + */ + public TransformParams setTransitionInfo(TransitionInfo transitionInfo) { + mTransitionInfo = transitionInfo; + return this; + } + /** * Sets the SyncRtSurfaceTransactionApplierCompat that will apply the SurfaceParams that * are computed based on these TransformParams. @@ -152,6 +164,9 @@ public class TransformParams { builder.setAlpha(getTargetAlpha()); } targetProxy.onBuildTargetParams(builder, app, this); + // Override the corner radius for {@code app} with the leash used by Shell, so that it + // doesn't interfere with the window clip and corner radius applied here. + overrideChangeLeashCornerRadiusToZero(app, transaction.getTransaction()); } // always put wallpaper layer to bottom. @@ -163,6 +178,28 @@ public class TransformParams { return transaction; } + private void overrideChangeLeashCornerRadiusToZero( + RemoteAnimationTarget app, SurfaceControl.Transaction transaction) { + if (!Flags.enableDesktopRecentsTransitionsCornersBugfix()) { + return; + } + SurfaceControl changeLeash = getChangeLeashForApp(app); + if (changeLeash != null) { + transaction.setCornerRadius(changeLeash, 0); + } + } + + private SurfaceControl getChangeLeashForApp(RemoteAnimationTarget app) { + if (mTransitionInfo == null) return null; + for (TransitionInfo.Change change : mTransitionInfo.getChanges()) { + if (change.getTaskInfo() == null) continue; + if (change.getTaskInfo().taskId == app.taskId) { + return change.getLeash(); + } + } + return null; + } + // Pubic getters so outside packages can read the values. public float getProgress() { diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index ab96474dc7..32d99ef043 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -5867,7 +5867,8 @@ public abstract class RecentsView< if (recentsAnimationTargets.hasDesktopTasks(mContext)) { gluer = new RemoteTargetGluer(getContext(), getSizeStrategy(), recentsAnimationTargets, true /* forDesktop */); - mRemoteTargetHandles = gluer.assignTargetsForDesktop(recentsAnimationTargets); + mRemoteTargetHandles = gluer.assignTargetsForDesktop( + recentsAnimationTargets, /* transitionInfo= */ null); } else { gluer = new RemoteTargetGluer(getContext(), getSizeStrategy(), recentsAnimationTargets, false); diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java index c334552bd7..7dea1549a2 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java @@ -370,7 +370,7 @@ public abstract class AbsSwipeUpHandlerTestCase< private void onRecentsAnimationStart(SWIPE_HANDLER absSwipeUpHandler) { runOnMainSync(() -> absSwipeUpHandler.onRecentsAnimationStart( - mRecentsAnimationController, mRecentsAnimationTargets)); + mRecentsAnimationController, mRecentsAnimationTargets, /* transitionInfo= */null)); } protected static void runOnMainSync(Runnable runnable) {