diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 425d9c326b..3add4dc372 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -287,4 +287,9 @@ 47dp 47dp 47dp + + + + + 20dp diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index cca41efaef..006628cc9e 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -75,6 +75,7 @@ import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.View.OnApplyWindowInsetsListener; +import android.view.ViewGroup; import android.view.ViewTreeObserver.OnDrawListener; import android.view.ViewTreeObserver.OnScrollChangedListener; import android.view.WindowInsets; @@ -127,12 +128,17 @@ import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; +import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.startingsurface.SplashScreenExitAnimationUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; +import java.util.Optional; import java.util.function.Consumer; /** @@ -248,6 +254,13 @@ public abstract class AbsSwipeUpHandler, private static final float MAX_QUICK_SWITCH_RECENTS_SCALE_PROGRESS = 0.07f; + // Controls task thumbnail splash's reveal animation after landing on a task from quickswitch. + // These values match WindowManager/Shell starting_window_app_reveal_* config values. + private static final int SPLASH_FADE_OUT_DURATION = 133; + private static final int SPLASH_APP_REVEAL_DELAY = 83; + private static final int SPLASH_APP_REVEAL_DURATION = 266; + private static final int SPLASH_ANIMATION_DURATION = 349; + /** * Used as the page index for logging when we return to the last task at the end of the gesture. */ @@ -285,6 +298,8 @@ public abstract class AbsSwipeUpHandler, private final long mTouchTimeMs; private long mLauncherFrameDrawnTime; + private final int mSplashMainWindowShiftLength; + private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch; private SwipePipToHomeAnimator mSwipePipToHomeAnimator; @@ -320,6 +335,9 @@ public abstract class AbsSwipeUpHandler, mQuickSwitchScaleScrollThreshold = context.getResources().getDimension( R.dimen.quick_switch_scaling_scroll_threshold); + mSplashMainWindowShiftLength = -context.getResources().getDimensionPixelSize( + R.dimen.starting_surface_exit_animation_window_shift_length); + initAfterSubclassConstructor(); initStateCallbacks(); } @@ -2069,16 +2087,59 @@ public abstract class AbsSwipeUpHandler, public void onTasksAppeared(RemoteAnimationTargetCompat[] appearedTaskTargets) { if (mRecentsAnimationController != null) { if (handleTaskAppeared(appearedTaskTargets)) { - mRecentsAnimationController.finish(false /* toRecents */, - null /* onFinishComplete */); - ActiveGestureLog.INSTANCE.addLog( - /* event= */ "finishRecentsAnimation", - /* extras= */ false, - /* gestureEvent= */ FINISH_RECENTS_ANIMATION); + Optional taskTargetOptional = + Arrays.stream(appearedTaskTargets) + .filter(targetCompat -> + targetCompat.taskId == mGestureState.getLastStartedTaskId()) + .findFirst(); + if (!taskTargetOptional.isPresent()) { + finishRecentsAnimationOnTasksAppeared(); + return; + } + RemoteAnimationTargetCompat taskTarget = taskTargetOptional.get(); + TaskView taskView = mRecentsView.getTaskViewByTaskId(taskTarget.taskId); + if (taskView == null || !taskView.getThumbnail().shouldShowSplashView()) { + finishRecentsAnimationOnTasksAppeared(); + return; + } + + ViewGroup splashView = mActivity.getDragLayer(); + + // When revealing the app with launcher splash screen, make the app visible + // and behind the splash view before the splash is animated away. + SyncRtSurfaceTransactionApplierCompat surfaceApplier = + new SyncRtSurfaceTransactionApplierCompat(splashView); + ArrayList params = new ArrayList<>(); + for (RemoteAnimationTargetCompat target : appearedTaskTargets) { + SurfaceParams.Builder builder = new SurfaceParams.Builder(target.leash); + builder.withAlpha(1); + builder.withLayer(-1); + params.add(builder.build()); + } + surfaceApplier.scheduleApply(params.toArray(new SurfaceParams[0])); + + SplashScreenExitAnimationUtils.startAnimations(splashView, taskTarget.leash, + mSplashMainWindowShiftLength, new TransactionPool(), new Rect(), + SPLASH_ANIMATION_DURATION, SPLASH_FADE_OUT_DURATION, + /* iconStartAlpha= */ 0, /* brandingStartAlpha= */ 0, + SPLASH_APP_REVEAL_DELAY, SPLASH_APP_REVEAL_DURATION, + new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + finishRecentsAnimationOnTasksAppeared(); + } + }); } } } + private void finishRecentsAnimationOnTasksAppeared() { + if (mRecentsAnimationController != null) { + mRecentsAnimationController.finish(false /* toRecents */, null /* onFinishComplete */); + } + ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); + } + /** * @return The index of the TaskView in RecentsView whose taskId matches the task that will * resume if we finish the controller. diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index 04a0af15c5..6792dc5445 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -370,7 +370,7 @@ public class TaskThumbnailView extends View { *

We want to show the splash if the aspect ratio or rotation of the thumbnail would be * different from the task. */ - boolean shouldShowSplashView() { + public boolean shouldShowSplashView() { return isThumbnailAspectRatioDifferentFromThumbnailData() || isThumbnailRotationDifferentFromTask(); } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index 0125775684..3fb7fee6a9 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -18,7 +18,6 @@ package com.android.quickstep.views; import static android.view.Display.DEFAULT_DISPLAY; import static android.widget.Toast.LENGTH_SHORT; -import static android.window.SplashScreen.SPLASH_SCREEN_STYLE_SOLID_COLOR; import static com.android.launcher3.Utilities.comp; import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor; @@ -669,9 +668,7 @@ public class TaskView extends FrameLayout implements Reusable { if (freezeTaskList) { opts.setFreezeRecentTasksReordering(); } - // TODO(b/202826469): Replace setSplashScreenStyle with setDisableStartingWindow. - opts.setSplashScreenStyle(mSnapshotView.shouldShowSplashView() - ? SPLASH_SCREEN_STYLE_SOLID_COLOR : opts.getSplashScreenStyle()); + opts.setDisableStartingWindow(mSnapshotView.shouldShowSplashView()); Task.TaskKey key = mTask.key; UI_HELPER_EXECUTOR.execute(() -> { if (!ActivityManagerWrapper.getInstance().startActivityFromRecents(key, opts)) {