diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java index 5d7d2ff6d8..d391c46e13 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/BaseSwipeUpHandler.java @@ -64,15 +64,16 @@ import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.AppWindowAnimationHelper; import com.android.quickstep.util.AppWindowAnimationHelper.TransformParams; import com.android.quickstep.util.RectFSpringAnim; -import com.android.quickstep.util.RemoteAnimationTargets; import com.android.quickstep.util.RecentsAnimationTargets; import com.android.quickstep.util.RecentsAnimationCallbacks.RecentsAnimationListener; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; +import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import java.util.ArrayList; import java.util.function.Consumer; /** @@ -115,7 +116,13 @@ public abstract class BaseSwipeUpHandler mRecentsAnimationStartCallbacks = new ArrayList<>(); protected T mActivity; protected Q mRecentsView; @@ -140,8 +147,7 @@ public abstract class BaseSwipeUpHandler { mTransformParams.setSyncTransactionApplier(applier); - mRecentsAnimationWrapper.runOnInit(() -> - mRecentsAnimationWrapper.targetSet.addDependentTransactionApplier(applier)); + runOnRecentsAnimationStart(() -> + mRecentsAnimationTargets.addDependentTransactionApplier(applier)); }); mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { @@ -219,8 +225,10 @@ public abstract class BaseSwipeUpHandler + mRecentsView.setRecentsAnimationTargets(mRecentsAnimationWrapper, + mRecentsAnimationTargets)); } protected void startNewTask(int successStateFlag, Consumer resultCallback) { @@ -256,8 +264,30 @@ public abstract class BaseSwipeUpHandler(mRecentsAnimationStartCallbacks)) { + action.run(); + } + mRecentsAnimationStartCallbacks.clear(); + } + } + + @Override + public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) { + mRecentsAnimationWrapper = null; + mRecentsAnimationTargets = null; + } + + @Override + public void onRecentsAnimationFinished(RecentsAnimationWrapper controller) { + mRecentsAnimationWrapper = null; + mRecentsAnimationTargets = null; } private Rect getStackBounds(DeviceProfile dp) { @@ -370,7 +418,7 @@ public abstract class BaseSwipeUpHandler mCallbacks = new ArrayList<>(); - - public RecentsAnimationTargets targetSet; + private final RecentsAnimationControllerCompat mController; + private final Consumer mOnFinishedListener; + private final boolean mShouldMinimizeSplitScreen; private boolean mWindowThresholdCrossed = false; - private final InputConsumerController mInputConsumerController; - private final Supplier mInputProxySupplier; - + private InputConsumerController mInputConsumerController; + private Supplier mInputProxySupplier; private InputConsumer mInputConsumer; private boolean mTouchInProgress; - private boolean mFinishPending; - public RecentsAnimationWrapper(InputConsumerController inputConsumerController, - Supplier inputProxySupplier) { - mInputConsumerController = inputConsumerController; - mInputProxySupplier = inputProxySupplier; + public RecentsAnimationWrapper(RecentsAnimationControllerCompat controller, + boolean shouldMinimizeSplitScreen, + Consumer onFinishedListener) { + mController = controller; + mOnFinishedListener = onFinishedListener; + mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen; + + setWindowThresholdCrossed(mWindowThresholdCrossed); } - public boolean hasTargets() { - return targetSet != null && targetSet.hasTargets(); + /** + * Synchronously takes a screenshot of the task with the given {@param taskId} if the task is + * currently being animated. + */ + public ThumbnailData screenshotTask(int taskId) { + return mController != null ? mController.screenshotTask(taskId) : null; + } + + /** + * Indicates that the gesture has crossed the window boundary threshold and system UI can be + * update the represent the window behind + */ + public void setWindowThresholdCrossed(boolean windowThresholdCrossed) { + if (mWindowThresholdCrossed != windowThresholdCrossed) { + mWindowThresholdCrossed = windowThresholdCrossed; + UI_HELPER_EXECUTOR.execute(() -> { + mController.setAnimationTargetsBehindSystemBars(!windowThresholdCrossed); + if (mShouldMinimizeSplitScreen && windowThresholdCrossed) { + // NOTE: As a workaround for conflicting animations (Launcher animating the task + // leash, and SystemUI resizing the docked stack, which resizes the task), we + // currently only set the minimized mode, and not the inverse. + // TODO: Synchronize the minimize animation with the launcher animation + mController.setSplitScreenMinimized(windowThresholdCrossed); + } + }); + } + } + + /** + * Notifies the controller that we want to defer cancel until the next app transition starts. + * If {@param screenshot} is set, then we will receive a screenshot on the next + * {@link RecentsAnimationCallbacks#onAnimationCanceled(ThumbnailData)} and we must also call + * {@link #cleanupScreenshot()} when that screenshot is no longer used. + */ + public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) { + mController.setDeferCancelUntilNextTransition(defer, screenshot); + } + + /** + * Cleans up the screenshot previously returned from + * {@link RecentsAnimationCallbacks#onAnimationCanceled(ThumbnailData)}. + */ + public void cleanupScreenshot() { + UI_HELPER_EXECUTOR.execute(() -> mController.cleanupScreenshot()); } @UiThread - public synchronized void setController(RecentsAnimationTargets targetSet) { - Preconditions.assertUIThread(); - this.targetSet = targetSet; - - if (targetSet == null) { - return; - } - targetSet.setWindowThresholdCrossed(mWindowThresholdCrossed); - - if (!mCallbacks.isEmpty()) { - for (Runnable action : new ArrayList<>(mCallbacks)) { - action.run(); - } - mCallbacks.clear(); - } + public void finishAnimationToHome() { + finishAndClear(true /* toRecents */, null, false /* sendUserLeaveHint */); } - public synchronized void runOnInit(Runnable action) { - if (targetSet == null) { - mCallbacks.add(action); - } else { - action.run(); - } + @UiThread + public void finishAnimationToApp() { + finishAndClear(false /* toRecents */, null, false /* sendUserLeaveHint */); } /** See {@link #finish(boolean, Runnable, boolean)} */ @@ -127,34 +159,36 @@ public class RecentsAnimationWrapper { private void finishAndClear(boolean toRecents, Runnable onFinishComplete, boolean sendUserLeaveHint) { - RecentsAnimationTargets controller = targetSet; - targetSet = null; disableInputProxy(); - if (controller != null) { - controller.finishController(toRecents, onFinishComplete, sendUserLeaveHint); - } + finishController(toRecents, onFinishComplete, sendUserLeaveHint); } - public void enableInputConsumer() { - if (targetSet != null) { - targetSet.enableInputConsumer(); - } + @UiThread + public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { + mOnFinishedListener.accept(this); + UI_HELPER_EXECUTOR.execute(() -> { + mController.setInputConsumerEnabled(false); + mController.finish(toRecents, sendUserLeaveHint); + if (callback != null) { + MAIN_EXECUTOR.execute(callback); + } + }); } /** - * Indicates that the gesture has crossed the window boundary threshold and system UI can be - * update the represent the window behind + * Enables the input consumer to start intercepting touches in the app window. */ - public void setWindowThresholdCrossed(boolean windowThresholdCrossed) { - if (mWindowThresholdCrossed != windowThresholdCrossed) { - mWindowThresholdCrossed = windowThresholdCrossed; - if (targetSet != null) { - targetSet.setWindowThresholdCrossed(windowThresholdCrossed); - } - } + public void enableInputConsumer() { + UI_HELPER_EXECUTOR.submit(() -> { + mController.hideCurrentInputMethod(); + mController.setInputConsumerEnabled(true); + }); } - public void enableInputProxy() { + public void enableInputProxy(InputConsumerController inputConsumerController, + Supplier inputProxySupplier) { + mInputProxySupplier = inputProxySupplier; + mInputConsumerController = inputConsumerController; mInputConsumerController.setInputListener(this::onInputConsumerEvent); } @@ -165,7 +199,9 @@ public class RecentsAnimationWrapper { mInputConsumer.onMotionEvent(dummyCancel); dummyCancel.recycle(); } - mInputConsumerController.setInputListener(null); + if (mInputConsumerController != null) { + mInputConsumerController.setInputListener(null); + } } private boolean onInputConsumerEvent(InputEvent ev) { @@ -214,14 +250,4 @@ public class RecentsAnimationWrapper { return true; } - - public void setDeferCancelUntilNextTransition(boolean defer, boolean screenshot) { - if (targetSet != null) { - targetSet.controller.setDeferCancelUntilNextTransition(defer, screenshot); - } - } - - public RecentsAnimationTargets getController() { - return targetSet; - } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java index 6b98a89abc..e09c9cb8fa 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java @@ -38,11 +38,9 @@ public class SwipeSharedState implements RecentsAnimationListener { private OverviewComponentObserver mOverviewComponentObserver; private RecentsAnimationCallbacks mRecentsAnimationListener; + private RecentsAnimationWrapper mLastRecentsAnimationController; private RecentsAnimationTargets mLastAnimationTarget; - // TODO: Remove - private Runnable mRecentsAnimationCanceledCallback; - private boolean mLastAnimationCancelled = false; private boolean mLastAnimationRunning = false; @@ -57,13 +55,35 @@ public class SwipeSharedState implements RecentsAnimationListener { } @Override - public final void onRecentsAnimationStart(RecentsAnimationTargets targetSet) { + public final void onRecentsAnimationStart(RecentsAnimationWrapper controller, + RecentsAnimationTargets targetSet) { + mLastRecentsAnimationController = controller; mLastAnimationTarget = targetSet; mLastAnimationCancelled = false; mLastAnimationRunning = true; } + @Override + public final void onRecentsAnimationCanceled(ThumbnailData thumbnailData) { + if (thumbnailData != null) { + mOverviewComponentObserver.getActivityControlHelper().switchToScreenshot(thumbnailData, + () -> { + mLastRecentsAnimationController.cleanupScreenshot(); + clearAnimationState(); + }); + } else { + clearAnimationState(); + } + } + + @Override + public final void onRecentsAnimationFinished(RecentsAnimationWrapper controller) { + if (mLastRecentsAnimationController == controller) { + mLastAnimationRunning = false; + } + } + private void clearAnimationTarget() { if (mLastAnimationTarget != null) { mLastAnimationTarget.release(); @@ -71,42 +91,23 @@ public class SwipeSharedState implements RecentsAnimationListener { } } - @Override - public final void onRecentsAnimationCanceled(ThumbnailData thumbnailData) { - if (thumbnailData != null) { - mOverviewComponentObserver.getActivityControlHelper().switchToScreenshot(thumbnailData, - () -> { - if (mRecentsAnimationCanceledCallback != null) { - mRecentsAnimationCanceledCallback.run(); - } - clearAnimationState(); - }); - } else { - clearAnimationState(); - } - } - - public void setRecentsAnimationCanceledCallback(Runnable callback) { - mRecentsAnimationCanceledCallback = callback; - } - private void clearAnimationState() { clearAnimationTarget(); mLastAnimationCancelled = true; mLastAnimationRunning = false; - mRecentsAnimationCanceledCallback = null; } private void clearListenerState(boolean finishAnimation) { if (mRecentsAnimationListener != null) { mRecentsAnimationListener.removeListener(this); - mRecentsAnimationListener.cancelListener(); - if (mLastAnimationRunning && mLastAnimationTarget != null) { + mRecentsAnimationListener.notifyAnimationCanceled(); + if (mLastAnimationRunning && mLastRecentsAnimationController != null) { Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), finishAnimation - ? mLastAnimationTarget::finishAnimation - : mLastAnimationTarget::cancelAnimation); + ? mLastRecentsAnimationController::finishAnimationToHome + : mLastRecentsAnimationController::finishAnimationToApp); + mLastRecentsAnimationController = null; mLastAnimationTarget = null; } } @@ -116,12 +117,6 @@ public class SwipeSharedState implements RecentsAnimationListener { mLastAnimationRunning = false; } - private void onSwipeAnimationFinished(RecentsAnimationTargets targetSet) { - if (mLastAnimationTarget == targetSet) { - mLastAnimationRunning = false; - } - } - public RecentsAnimationCallbacks newRecentsAnimationListenerSet() { Preconditions.assertUIThread(); @@ -137,8 +132,7 @@ public class SwipeSharedState implements RecentsAnimationListener { clearListenerState(false /* finishAnimation */); boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false : mOverviewComponentObserver.getActivityControlHelper().shouldMinimizeSplitScreen(); - mRecentsAnimationListener = new RecentsAnimationCallbacks( - shouldMinimiseSplitScreen, this::onSwipeAnimationFinished); + mRecentsAnimationListener = new RecentsAnimationCallbacks(shouldMinimiseSplitScreen); mRecentsAnimationListener.addListener(this); return mRecentsAnimationListener; } @@ -148,8 +142,9 @@ public class SwipeSharedState implements RecentsAnimationListener { } public void applyActiveRecentsAnimationState(RecentsAnimationListener listener) { - if (mLastAnimationTarget != null) { - listener.onRecentsAnimationStart(mLastAnimationTarget); + if (mLastRecentsAnimationController != null) { + listener.onRecentsAnimationStart(mLastRecentsAnimationController, + mLastAnimationTarget); } else if (mLastAnimationCancelled) { listener.onRecentsAnimationCanceled(null); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 0700f7b020..41d94714a6 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -414,10 +414,9 @@ public class TouchInteractionService extends Service implements // Do not change mConsumer as if there is an ongoing QuickSwitch gesture, we should // not interrupt it. QuickSwitch assumes that interruption can only happen if the // next gesture is also quick switch. - mUncheckedConsumer = - new AssistantInputConsumer(this, - mOverviewComponentObserver.getActivityControlHelper(), - InputConsumer.NO_OP, mInputMonitorCompat); + mUncheckedConsumer = new AssistantInputConsumer(this, + mOverviewComponentObserver.getActivityControlHelper(), + InputConsumer.NO_OP, mInputMonitorCompat); } else { mUncheckedConsumer = InputConsumer.NO_OP; } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index b0628e55df..69928f3a2c 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -291,9 +291,6 @@ public class WindowTransformSwipeHandler mStateCallback.addCallback(STATE_HANDLER_INVALIDATED | STATE_RESUME_LAST_TASK, this::notifyTransitionCancelled); - mStateCallback.addCallback(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED, - mRecentsAnimationWrapper::enableInputConsumer); - if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) { mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT | STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT, @@ -417,7 +414,7 @@ public class WindowTransformSwipeHandler } private void sendRemoteAnimationsToAnimationFactory() { - mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationWrapper.targetSet); + mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationTargets); } private void initializeLauncherAnimationController() { @@ -464,9 +461,9 @@ public class WindowTransformSwipeHandler if (mMode != Mode.NO_BUTTON || mRecentsView == null) { return; } - RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationWrapper.targetSet == null + RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets == null ? null - : mRecentsAnimationWrapper.targetSet.findTask(mRunningTaskId); + : mRecentsAnimationTargets.findTask(mRunningTaskId); final boolean recentsAttachedToAppWindow; int runningTaskIndex = mRecentsView.getRunningTaskIndex(); if (mGestureEndTarget != null) { @@ -548,15 +545,13 @@ public class WindowTransformSwipeHandler @Override public void updateFinalShift() { - - RecentsAnimationTargets controller = mRecentsAnimationWrapper.getController(); - if (controller != null) { + if (mRecentsAnimationTargets != null) { applyTransformUnchecked(); updateSysUiFlags(mCurrentShift.value); } if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { - if (mRecentsAnimationWrapper.getController() != null) { + if (mRecentsAnimationTargets != null) { mLiveTileOverlay.update(mAppWindowAnimationHelper.getCurrentRectWithInsets(), mAppWindowAnimationHelper.getCurrentCornerRadius()); } @@ -599,17 +594,24 @@ public class WindowTransformSwipeHandler : centermostTask.getThumbnail().getSysUiStatusNavFlags(); boolean useHomeScreenFlags = windowProgress > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD; // We will handle the sysui flags based on the centermost task view. - mRecentsAnimationWrapper.setWindowThresholdCrossed(centermostTaskFlags != 0 - || useHomeScreenFlags); + if (mRecentsAnimationWrapper != null) { + mRecentsAnimationWrapper.setWindowThresholdCrossed(centermostTaskFlags != 0 + || useHomeScreenFlags); + } int sysuiFlags = useHomeScreenFlags ? 0 : centermostTaskFlags; mActivity.getSystemUiController().updateUiState(UI_STATE_OVERVIEW, sysuiFlags); } } @Override - public void onRecentsAnimationStart(RecentsAnimationTargets targetSet) { - super.onRecentsAnimationStart(targetSet); + public void onRecentsAnimationStart(RecentsAnimationWrapper controller, + RecentsAnimationTargets targetSet) { ActiveGestureLog.INSTANCE.addLog("startRecentsAnimationCallback", targetSet.apps.length); + super.onRecentsAnimationStart(controller, targetSet); + + // Only add the callback to enable the input consumer after we actually have the controller + mStateCallback.addCallback(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED, + mRecentsAnimationWrapper::enableInputConsumer); setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED); mPassedOverviewThreshold = false; @@ -617,7 +619,8 @@ public class WindowTransformSwipeHandler @Override public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) { - mRecentsAnimationWrapper.setController(null); + super.onRecentsAnimationCanceled(thumbnailData); + mRecentsView.setRecentsAnimationTargets(null, null); mActivityInitListener.unregister(); setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED); ActiveGestureLog.INSTANCE.addLog("cancelRecentsAnimation"); @@ -707,7 +710,7 @@ public class WindowTransformSwipeHandler final GestureEndTarget endTarget; final boolean goingToNewTask; if (mRecentsView != null) { - if (!mRecentsAnimationWrapper.hasTargets()) { + if (!hasTargets()) { // If there are no running tasks, then we can assume that this is a continuation of // the last gesture, but after the recents animation has finished goingToNewTask = true; @@ -810,8 +813,9 @@ public class WindowTransformSwipeHandler } } - if (endTarget.isLauncher) { - mRecentsAnimationWrapper.enableInputProxy(); + if (endTarget.isLauncher && mRecentsAnimationWrapper != null) { + mRecentsAnimationWrapper.enableInputProxy(mInputConsumer, + this::createNewInputProxyHandler); } if (endTarget == HOME) { @@ -866,7 +870,7 @@ public class WindowTransformSwipeHandler @UiThread private void animateToProgress(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) { - mRecentsAnimationWrapper.runOnInit(() -> animateToProgressInternal(start, end, duration, + runOnRecentsAnimationStart(() -> animateToProgressInternal(start, end, duration, interpolator, target, velocityPxPerMs)); } @@ -1108,25 +1112,24 @@ public class WindowTransformSwipeHandler } private void switchToScreenshot() { - RecentsAnimationTargets controller = mRecentsAnimationWrapper.getController(); if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { - if (controller != null) { + if (mRecentsAnimationWrapper != null) { // Update the screenshot of the task if (mTaskSnapshot == null) { - mTaskSnapshot = controller.screenshotTask(mRunningTaskId); + mTaskSnapshot = mRecentsAnimationWrapper.screenshotTask(mRunningTaskId); } mRecentsView.updateThumbnail(mRunningTaskId, mTaskSnapshot, false /* refreshNow */); } setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); - } else if (!mRecentsAnimationWrapper.hasTargets()) { + } else if (!hasTargets()) { // If there are no targets, then we don't need to capture anything setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); } else { boolean finishTransitionPosted = false; - if (controller != null) { + if (mRecentsAnimationWrapper != null) { // Update the screenshot of the task if (mTaskSnapshot == null) { - mTaskSnapshot = controller.screenshotTask(mRunningTaskId); + mTaskSnapshot = mRecentsAnimationWrapper.screenshotTask(mRunningTaskId); } final TaskView taskView; if (mGestureEndTarget == HOME) { @@ -1155,7 +1158,7 @@ public class WindowTransformSwipeHandler private void finishCurrentTransitionToRecents() { if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { setStateOnUiThread(STATE_CURRENT_TASK_FINISHED); - } else if (!mRecentsAnimationWrapper.hasTargets()) { + } else if (!hasTargets()) { // If there are no targets, then there is nothing to finish setStateOnUiThread(STATE_CURRENT_TASK_FINISHED); } else { @@ -1180,8 +1183,10 @@ public class WindowTransformSwipeHandler private void setupLauncherUiAfterSwipeUpToRecentsAnimation() { endLauncherTransitionController(); mActivityControlHelper.onSwipeUpToRecentsComplete(mActivity); - mRecentsAnimationWrapper.setDeferCancelUntilNextTransition(true /* defer */, - true /* screenshot */); + if (mRecentsAnimationWrapper != null) { + mRecentsAnimationWrapper.setDeferCancelUntilNextTransition(true /* defer */, + true /* screenshot */); + } mRecentsView.onSwipeUpAnimationSuccess(); RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java index 25b4fe4f15..2d95d758bc 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java @@ -42,6 +42,7 @@ import com.android.launcher3.util.DefaultDisplay; import com.android.quickstep.LockScreenRecentsActivity; import com.android.quickstep.MultiStateCallback; import com.android.quickstep.RecentsAnimationDeviceState; +import com.android.quickstep.RecentsAnimationWrapper; import com.android.quickstep.SwipeSharedState; import com.android.quickstep.util.AppWindowAnimationHelper; import com.android.quickstep.util.RecentsAnimationCallbacks; @@ -91,7 +92,8 @@ public class DeviceLockedInputConsumer implements InputConsumer, private boolean mThresholdCrossed = false; - private RecentsAnimationTargets mTargetSet; + private RecentsAnimationWrapper mRecentsAnimationController; + private RecentsAnimationTargets mRecentsAnimationTargets; public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState, SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat, @@ -216,8 +218,10 @@ public class DeviceLockedInputConsumer implements InputConsumer, } @Override - public void onRecentsAnimationStart(RecentsAnimationTargets targetSet) { - mTargetSet = targetSet; + public void onRecentsAnimationStart(RecentsAnimationWrapper controller, + RecentsAnimationTargets targetSet) { + mRecentsAnimationController = controller; + mRecentsAnimationTargets = targetSet; Rect displaySize = new Rect(0, 0, mDisplaySize.x, mDisplaySize.y); RemoteAnimationTargetCompat targetCompat = targetSet.findTask(mRunningTaskId); @@ -227,7 +231,7 @@ public class DeviceLockedInputConsumer implements InputConsumer, Utilities.scaleRectAboutCenter(displaySize, SCALE_DOWN); displaySize.offsetTo(displaySize.left, 0); - mTransformParams.setTargetSet(mTargetSet) + mTransformParams.setTargetSet(mRecentsAnimationTargets) .setLauncherOnTop(true); mAppWindowAnimationHelper.updateTargetRect(displaySize); mAppWindowAnimationHelper.applyTransform(mTransformParams); @@ -237,12 +241,13 @@ public class DeviceLockedInputConsumer implements InputConsumer, @Override public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) { - mTargetSet = null; + mRecentsAnimationController = null; + mRecentsAnimationTargets = null; } private void endRemoteAnimation() { - if (mTargetSet != null) { - mTargetSet.finishController( + if (mRecentsAnimationController != null) { + mRecentsAnimationController.finishController( false /* toRecents */, null /* callback */, false /* sendUserLeaveHint */); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java index 59efb2d05f..4d9ed5324a 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/FallbackNoButtonInputConsumer.java @@ -45,6 +45,7 @@ import com.android.quickstep.BaseSwipeUpHandler; import com.android.quickstep.MultiStateCallback; import com.android.quickstep.OverviewComponentObserver; import com.android.quickstep.RecentsActivity; +import com.android.quickstep.RecentsAnimationWrapper; import com.android.quickstep.RecentsModel; import com.android.quickstep.SwipeSharedState; import com.android.quickstep.fallback.FallbackRecentsView; @@ -157,7 +158,7 @@ public class FallbackNoButtonInputConsumer extends } private void onLauncherAlphaChanged() { - if (mRecentsAnimationWrapper.targetSet != null && mEndTarget == null) { + if (mRecentsAnimationTargets != null && mEndTarget == null) { applyTransformUnchecked(); } } @@ -231,9 +232,11 @@ public class FallbackNoButtonInputConsumer extends @Override public void updateFinalShift() { mTransformParams.setProgress(mCurrentShift.value); - mRecentsAnimationWrapper.setWindowThresholdCrossed(!mInQuickSwitchMode - && (mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD)); - if (mRecentsAnimationWrapper.targetSet != null) { + if (mRecentsAnimationWrapper != null) { + mRecentsAnimationWrapper.setWindowThresholdCrossed(!mInQuickSwitchMode + && (mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD)); + } + if (mRecentsAnimationTargets != null) { applyTransformUnchecked(); } } @@ -333,8 +336,7 @@ public class FallbackNoButtonInputConsumer extends break; } - ThumbnailData thumbnail = - mRecentsAnimationWrapper.targetSet.controller.screenshotTask(mRunningTaskId); + ThumbnailData thumbnail = mRecentsAnimationWrapper.screenshotTask(mRunningTaskId); mRecentsAnimationWrapper.setDeferCancelUntilNextTransition(true /* defer */, false /* screenshot */); @@ -348,7 +350,7 @@ public class FallbackNoButtonInputConsumer extends Intent intent = new Intent(mOverviewComponentObserver.getOverviewIntent()) .putExtras(extras); mContext.startActivity(intent, options.toBundle()); - mRecentsAnimationWrapper.targetSet.controller.cleanupScreenshot(); + mRecentsAnimationWrapper.cleanupScreenshot(); break; } case NEW_TASK: { @@ -364,7 +366,7 @@ public class FallbackNoButtonInputConsumer extends if (mInQuickSwitchMode) { // Recalculate the end target, some views might have been initialized after // gesture has ended. - if (mRecentsView == null || !mRecentsAnimationWrapper.hasTargets()) { + if (mRecentsView == null || !hasTargets()) { mEndTarget = LAST_TASK; } else { final int runningTaskIndex = mRecentsView.getRunningTaskIndex(); @@ -414,8 +416,9 @@ public class FallbackNoButtonInputConsumer extends } @Override - public void onRecentsAnimationStart(RecentsAnimationTargets targetSet) { - super.onRecentsAnimationStart(targetSet); + public void onRecentsAnimationStart(RecentsAnimationWrapper controller, + RecentsAnimationTargets targetSet) { + super.onRecentsAnimationStart(controller, targetSet); mRecentsAnimationWrapper.enableInputConsumer(); if (mRunningOverHome) { @@ -428,7 +431,7 @@ public class FallbackNoButtonInputConsumer extends @Override public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) { - mRecentsAnimationWrapper.setController(null); + mRecentsView.setRecentsAnimationTargets(null, null); setStateOnUiThread(STATE_HANDLER_INVALIDATED); } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationCallbacks.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationCallbacks.java index 415f7674b8..824b34dd05 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationCallbacks.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationCallbacks.java @@ -26,33 +26,30 @@ import androidx.annotation.UiThread; import com.android.launcher3.Utilities; import com.android.launcher3.util.Preconditions; import com.android.quickstep.TouchInteractionService; +import com.android.quickstep.RecentsAnimationWrapper; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import java.util.Set; -import java.util.function.Consumer; /** - * Wrapper around {@link com.android.systemui.shared.system.RecentsAnimationListener} which delegates callbacks to multiple listeners - * on the main thread + * Wrapper around {@link com.android.systemui.shared.system.RecentsAnimationListener} which + * delegates callbacks to multiple listeners on the main thread */ public class RecentsAnimationCallbacks implements com.android.systemui.shared.system.RecentsAnimationListener { private final Set mListeners = new ArraySet<>(); private final boolean mShouldMinimizeSplitScreen; - private final Consumer mOnFinishListener; - private RecentsAnimationControllerCompat mController; + + // TODO(141886704): Remove these references when they are no longer needed + private RecentsAnimationWrapper mController; private boolean mCancelled; - public RecentsAnimationCallbacks(boolean shouldMinimizeSplitScreen, - Consumer onFinishListener) { + public RecentsAnimationCallbacks(boolean shouldMinimizeSplitScreen) { mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen; - mOnFinishListener = onFinishListener; - TouchInteractionService.getSwipeSharedState().setRecentsAnimationCanceledCallback( - () -> mController.cleanupScreenshot()); } @UiThread @@ -67,26 +64,9 @@ public class RecentsAnimationCallbacks implements mListeners.remove(listener); } - // Called only in R+ platform - @BinderThread - public final void onAnimationStart(RecentsAnimationControllerCompat controller, - RemoteAnimationTargetCompat[] appTargets, - RemoteAnimationTargetCompat[] wallpaperTargets, - Rect homeContentInsets, Rect minimizedHomeBounds) { - mController = controller; - RecentsAnimationTargets targetSet = new RecentsAnimationTargets(controller, appTargets, - wallpaperTargets, homeContentInsets, minimizedHomeBounds, - mShouldMinimizeSplitScreen, mOnFinishListener); - - if (mCancelled) { - targetSet.cancelAnimation(); - } else { - Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> { - for (RecentsAnimationListener listener : getListeners()) { - listener.onRecentsAnimationStart(targetSet); - } - }); - } + public void notifyAnimationCanceled() { + mCancelled = true; + onAnimationCanceled(null); } // Called only in Q platform @@ -99,6 +79,29 @@ public class RecentsAnimationCallbacks implements homeContentInsets, minimizedHomeBounds); } + // Called only in R+ platform + @BinderThread + public final void onAnimationStart(RecentsAnimationControllerCompat animationController, + RemoteAnimationTargetCompat[] appTargets, + RemoteAnimationTargetCompat[] wallpaperTargets, + Rect homeContentInsets, Rect minimizedHomeBounds) { + RecentsAnimationTargets targetSet = new RecentsAnimationTargets(appTargets, + wallpaperTargets, homeContentInsets, minimizedHomeBounds); + mController = new RecentsAnimationWrapper(animationController, mShouldMinimizeSplitScreen, + this::onAnimationFinished); + + if (mCancelled) { + Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), + mController::finishAnimationToApp); + } else { + Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> { + for (RecentsAnimationListener listener : getListeners()) { + listener.onRecentsAnimationStart(mController, targetSet); + } + }); + } + } + @BinderThread @Override public final void onAnimationCanceled(ThumbnailData thumbnailData) { @@ -109,25 +112,31 @@ public class RecentsAnimationCallbacks implements }); } - private RecentsAnimationListener[] getListeners() { - return mListeners.toArray(new RecentsAnimationListener[mListeners.size()]); + private final void onAnimationFinished(RecentsAnimationWrapper controller) { + Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> { + for (RecentsAnimationListener listener : getListeners()) { + listener.onRecentsAnimationFinished(controller); + } + }); } - public void cancelListener() { - mCancelled = true; - onAnimationCanceled(null); + private RecentsAnimationListener[] getListeners() { + return mListeners.toArray(new RecentsAnimationListener[mListeners.size()]); } /** * Listener for the recents animation callbacks. */ public interface RecentsAnimationListener { - void onRecentsAnimationStart(RecentsAnimationTargets targetSet); + default void onRecentsAnimationStart(RecentsAnimationWrapper controller, + RecentsAnimationTargets targetSet) {} /** * Callback from the system when the recents animation is canceled. {@param thumbnailData} * is passed back for rendering screenshot to replace live tile. */ - void onRecentsAnimationCanceled(ThumbnailData thumbnailData); + default void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {} + + default void onRecentsAnimationFinished(RecentsAnimationWrapper controller) {} } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationTargets.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationTargets.java index 187a404b42..4013e92bfe 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationTargets.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RecentsAnimationTargets.java @@ -15,41 +15,27 @@ */ package com.android.quickstep.util; -import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; -import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import android.graphics.Rect; -import com.android.systemui.shared.recents.model.ThumbnailData; -import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import java.util.function.Consumer; - /** * Extension of {@link RemoteAnimationTargets} with additional information about swipe * up animation */ public class RecentsAnimationTargets extends RemoteAnimationTargets { - private final boolean mShouldMinimizeSplitScreen; - private final Consumer mOnFinishListener; - - public final RecentsAnimationControllerCompat controller; public final Rect homeContentInsets; public final Rect minimizedHomeBounds; - public RecentsAnimationTargets(RecentsAnimationControllerCompat controller, - RemoteAnimationTargetCompat[] apps, RemoteAnimationTargetCompat[] wallpapers, - Rect homeContentInsets, Rect minimizedHomeBounds, boolean shouldMinimizeSplitScreen, - Consumer onFinishListener) { + public RecentsAnimationTargets(RemoteAnimationTargetCompat[] apps, + RemoteAnimationTargetCompat[] wallpapers, Rect homeContentInsets, + Rect minimizedHomeBounds) { super(apps, wallpapers, MODE_CLOSING); - this.controller = controller; this.homeContentInsets = homeContentInsets; this.minimizedHomeBounds = minimizedHomeBounds; - this.mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen; - this.mOnFinishListener = onFinishListener; } public boolean hasTargets() { @@ -61,52 +47,7 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets { * the actual recents animation has finished. */ public RecentsAnimationTargets cloneWithoutTargets() { - return new RecentsAnimationTargets(controller, new RemoteAnimationTargetCompat[0], - new RemoteAnimationTargetCompat[0], homeContentInsets, minimizedHomeBounds, - mShouldMinimizeSplitScreen, mOnFinishListener); - } - - public void finishController(boolean toRecents, Runnable callback, boolean sendUserLeaveHint) { - mOnFinishListener.accept(this); - UI_HELPER_EXECUTOR.execute(() -> { - controller.setInputConsumerEnabled(false); - controller.finish(toRecents, sendUserLeaveHint); - - if (callback != null) { - MAIN_EXECUTOR.execute(callback); - } - }); - } - - public void enableInputConsumer() { - UI_HELPER_EXECUTOR.submit(() -> { - controller.hideCurrentInputMethod(); - controller.setInputConsumerEnabled(true); - }); - } - - public void setWindowThresholdCrossed(boolean thresholdCrossed) { - UI_HELPER_EXECUTOR.execute(() -> { - controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed); - if (mShouldMinimizeSplitScreen && thresholdCrossed) { - // NOTE: As a workaround for conflicting animations (Launcher animating the task - // leash, and SystemUI resizing the docked stack, which resizes the task), we - // currently only set the minimized mode, and not the inverse. - // TODO: Synchronize the minimize animation with the launcher animation - controller.setSplitScreenMinimized(thresholdCrossed); - } - }); - } - - public ThumbnailData screenshotTask(int taskId) { - return controller != null ? controller.screenshotTask(taskId) : null; - } - - public void cancelAnimation() { - finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); - } - - public void finishAnimation() { - finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); + return new RecentsAnimationTargets(new RemoteAnimationTargetCompat[0], + new RemoteAnimationTargetCompat[0], homeContentInsets, minimizedHomeBounds); } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java index 0f9184f48d..6a6043cec7 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java @@ -221,7 +221,7 @@ public class LauncherRecentsView extends RecentsView implements StateL public AppWindowAnimationHelper.TransformParams getLiveTileParams( boolean mightNeedToRefill) { if (!mEnableDrawingLiveTile || mRecentsAnimationWrapper == null - || mAppWindowAnimationHelper == null) { + || mRecentsAnimationTargets == null || mAppWindowAnimationHelper == null) { return null; } TaskView taskView = getRunningTaskView(); @@ -245,7 +245,7 @@ public class LauncherRecentsView extends RecentsView implements StateL mTransformParams.setProgress(1f) .setCurrentRectAndTargetAlpha(mTempRectF, taskView.getAlpha()) .setSyncTransactionApplier(mSyncTransactionApplier) - .setTargetSet(mRecentsAnimationWrapper.targetSet) + .setTargetSet(mRecentsAnimationTargets) .setLauncherOnTop(true); } return mTransformParams; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java index cefe2647ee..67cd3d6bd8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java @@ -108,6 +108,7 @@ import com.android.quickstep.TaskThumbnailCache; import com.android.quickstep.TaskUtils; import com.android.quickstep.ViewUtils; import com.android.quickstep.util.AppWindowAnimationHelper; +import com.android.quickstep.util.RecentsAnimationTargets; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; @@ -156,6 +157,7 @@ public abstract class RecentsView extends PagedView impl }; protected RecentsAnimationWrapper mRecentsAnimationWrapper; + protected RecentsAnimationTargets mRecentsAnimationTargets; protected AppWindowAnimationHelper mAppWindowAnimationHelper; protected SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier; protected int mTaskWidth; @@ -808,6 +810,7 @@ public abstract class RecentsView extends PagedView impl mTaskListChangeId = -1; mRecentsAnimationWrapper = null; + mRecentsAnimationTargets = null; mAppWindowAnimationHelper = null; unloadVisibleTaskData(); @@ -1692,10 +1695,14 @@ public abstract class RecentsView extends PagedView impl public void redrawLiveTile(boolean mightNeedToRefill) { } - public void setRecentsAnimationWrapper(RecentsAnimationWrapper recentsAnimationWrapper) { + // TODO: To be removed in a follow up CL + public void setRecentsAnimationTargets(RecentsAnimationWrapper recentsAnimationWrapper, + RecentsAnimationTargets recentsAnimationTargets) { mRecentsAnimationWrapper = recentsAnimationWrapper; + mRecentsAnimationTargets = recentsAnimationTargets; } + // TODO: To be removed in a follow up CL public void setAppWindowAnimationHelper(AppWindowAnimationHelper appWindowAnimationHelper) { mAppWindowAnimationHelper = appWindowAnimationHelper; } diff --git a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargets.java b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargets.java index ff726a1efe..f971c47d2e 100644 --- a/quickstep/src/com/android/quickstep/util/RemoteAnimationTargets.java +++ b/quickstep/src/com/android/quickstep/util/RemoteAnimationTargets.java @@ -86,6 +86,9 @@ public class RemoteAnimationTargets { for (RemoteAnimationTargetCompat target : unfilteredApps) { target.release(); } + for (RemoteAnimationTargetCompat target : wallpapers) { + target.release(); + } } else { applier.addAfterApplyCallback(this::release); }