Use wm shell splash screen animation to reveal app after tasks have appeared.
Bug: 202826469
Test: manual
Change-Id: I6a9e8a932849c30f7b572119a7f607178b5a6437
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index c85e71c..d2d1f52 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -283,4 +283,9 @@
<dimen name="taskbar_button_margin_4_5">47dp</dimen>
<dimen name="taskbar_button_margin_4_4">47dp</dimen>
<dimen name="taskbar_button_margin_default">47dp</dimen>
+
+ <!-- Launcher splash screen -->
+ <!-- Note: keep this value in sync with the WindowManager/Shell dimens.xml -->
+ <!-- starting_surface_exit_animation_window_shift_length -->
+ <dimen name="starting_surface_exit_animation_window_shift_length">20dp</dimen>
</resources>
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index f3630c1..d68db57 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -76,6 +76,7 @@
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;
@@ -128,12 +129,17 @@
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;
/**
@@ -249,6 +255,13 @@
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.
*/
@@ -286,6 +299,8 @@
private final long mTouchTimeMs;
private long mLauncherFrameDrawnTime;
+ private final int mSplashMainWindowShiftLength;
+
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
private SwipePipToHomeAnimator mSwipePipToHomeAnimator;
@@ -321,6 +336,9 @@
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();
}
@@ -2061,16 +2079,59 @@
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<RemoteAnimationTargetCompat> 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<SurfaceParams> 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 d7a8599..1e044db 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -373,7 +373,7 @@
* <p>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 a81f95f..25cc28f 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -18,7 +18,6 @@
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;
@@ -667,9 +666,7 @@
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)) {