Merge "Block relayout during transition to desktop" into udc-dev am: 3be325fb64
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/22298053
Change-Id: I8ff9978a96c8566101ab9b8207e9152c09ae9127
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
index e1a56a1..6b6a7bc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java
@@ -153,6 +153,8 @@
@Override
public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
+ mWindowDecorViewModel.onTransitionMerged(merged, playing);
+
final List<ActivityManager.RunningTaskInfo> infoOfMerged =
mTransitionToTaskInfo.get(merged);
if (infoOfMerged == null) {
@@ -169,8 +171,6 @@
} else {
mTransitionToTaskInfo.put(playing, infoOfMerged);
}
-
- mWindowDecorViewModel.onTransitionMerged(merged, playing);
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
index 4ef3350..4cda571 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java
@@ -113,11 +113,6 @@
private boolean mDragToDesktopAnimationStarted;
private float mCaptionDragStartX;
- // These values keep track of any transitions to freeform to stop relayout from running on
- // changing task so that shellTransitions has a chance to animate the transition
- private int mPauseRelayoutForTask = -1;
- private IBinder mTransitionPausingRelayout;
-
public DesktopModeWindowDecorViewModel(
Context context,
Handler mainHandler,
@@ -195,22 +190,25 @@
@NonNull TransitionInfo info,
@NonNull TransitionInfo.Change change) {
if (change.getMode() == WindowManager.TRANSIT_CHANGE
- && info.getType() == Transitions.TRANSIT_ENTER_DESKTOP_MODE) {
- mTransitionPausingRelayout = transition;
+ && (info.getType() == Transitions.TRANSIT_ENTER_DESKTOP_MODE)) {
+ mWindowDecorByTaskId.get(change.getTaskInfo().taskId)
+ .addTransitionPausingRelayout(transition);
}
}
@Override
public void onTransitionMerged(@NonNull IBinder merged, @NonNull IBinder playing) {
- if (merged.equals(mTransitionPausingRelayout)) {
- mTransitionPausingRelayout = playing;
+ for (int i = 0; i < mWindowDecorByTaskId.size(); i++) {
+ final DesktopModeWindowDecoration decor = mWindowDecorByTaskId.valueAt(i);
+ decor.mergeTransitionPausingRelayout(merged, playing);
}
}
@Override
public void onTransitionFinished(@NonNull IBinder transition) {
- if (transition.equals(mTransitionPausingRelayout)) {
- mPauseRelayoutForTask = -1;
+ for (int i = 0; i < mWindowDecorByTaskId.size(); i++) {
+ final DesktopModeWindowDecoration decor = mWindowDecorByTaskId.valueAt(i);
+ decor.removeTransitionPausingRelayout(transition);
}
}
@@ -225,12 +223,7 @@
incrementEventReceiverTasks(taskInfo.displayId);
}
- // TaskListener callbacks and shell transitions aren't synchronized, so starting a shell
- // transition can trigger an onTaskInfoChanged call that updates the task's SurfaceControl
- // and interferes with the transition animation that is playing at the same time.
- if (taskInfo.taskId != mPauseRelayoutForTask) {
- decoration.relayout(taskInfo);
- }
+ decoration.relayout(taskInfo);
}
@Override
@@ -555,8 +548,7 @@
relevantDecor.mTaskInfo.displayId);
if (ev.getY() > 2 * statusBarHeight) {
if (DesktopModeStatus.isProto2Enabled()) {
- mPauseRelayoutForTask = relevantDecor.mTaskInfo.taskId;
- centerAndMoveToDesktopWithAnimation(relevantDecor, ev);
+ animateToDesktop(relevantDecor, ev);
} else if (DesktopModeStatus.isProto1Enabled()) {
mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(true));
}
@@ -632,6 +624,15 @@
}
/**
+ * Blocks relayout until transition is finished and transitions to Desktop
+ */
+ private void animateToDesktop(DesktopModeWindowDecoration relevantDecor,
+ MotionEvent ev) {
+ relevantDecor.incrementRelayoutBlock();
+ centerAndMoveToDesktopWithAnimation(relevantDecor, ev);
+ }
+
+ /**
* Animates a window to the center, grows to freeform size, and transitions to Desktop Mode.
* @param relevantDecor the window decor of the task to be animated
* @param ev the motion event that triggers the animation
@@ -658,10 +659,9 @@
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
- mDesktopTasksController.ifPresent(
- c -> c.onDragPositioningEndThroughStatusBar(
- relevantDecor.mTaskInfo,
- calculateFreeformBounds(FINAL_FREEFORM_SCALE)));
+ mDesktopTasksController.ifPresent(c ->
+ c.onDragPositioningEndThroughStatusBar(relevantDecor.mTaskInfo,
+ calculateFreeformBounds(FINAL_FREEFORM_SCALE)));
}
});
animator.start();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
index b1c3791..95ed42a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java
@@ -30,6 +30,7 @@
import android.graphics.Region;
import android.graphics.drawable.Drawable;
import android.os.Handler;
+import android.os.IBinder;
import android.util.Log;
import android.view.Choreographer;
import android.view.MotionEvent;
@@ -49,6 +50,9 @@
import com.android.wm.shell.windowdecor.viewholder.DesktopModeFocusedWindowDecorationViewHolder;
import com.android.wm.shell.windowdecor.viewholder.DesktopModeWindowDecorationViewHolder;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* Defines visuals and behaviors of a window decoration of a caption bar and shadows. It works with
* {@link DesktopModeWindowDecorViewModel}.
@@ -83,6 +87,9 @@
private TaskCornersListener mCornersListener;
+ private final Set<IBinder> mTransitionsPausingRelayout = new HashSet<>();
+ private int mRelayoutBlock;
+
DesktopModeWindowDecoration(
Context context,
DisplayController displayController,
@@ -134,6 +141,13 @@
@Override
void relayout(ActivityManager.RunningTaskInfo taskInfo) {
+ // TaskListener callbacks and shell transitions aren't synchronized, so starting a shell
+ // transition can trigger an onTaskInfoChanged call that updates the task's SurfaceControl
+ // and interferes with the transition animation that is playing at the same time.
+ if (mRelayoutBlock > 0) {
+ return;
+ }
+
final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
// Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is
// synced with the buffer transaction (that draws the View). Both will be shown on screen
@@ -455,6 +469,40 @@
return cornersRegion;
}
+ /**
+ * If transition exists in mTransitionsPausingRelayout, remove the transition and decrement
+ * mRelayoutBlock
+ */
+ void removeTransitionPausingRelayout(IBinder transition) {
+ if (mTransitionsPausingRelayout.remove(transition)) {
+ mRelayoutBlock--;
+ }
+ }
+
+ /**
+ * Add transition to mTransitionsPausingRelayout
+ */
+ void addTransitionPausingRelayout(IBinder transition) {
+ mTransitionsPausingRelayout.add(transition);
+ }
+
+ /**
+ * If two transitions merge and the merged transition is in mTransitionsPausingRelayout,
+ * remove the merged transition from the set and add the transition it was merged into.
+ */
+ public void mergeTransitionPausingRelayout(IBinder merged, IBinder playing) {
+ if (mTransitionsPausingRelayout.remove(merged)) {
+ mTransitionsPausingRelayout.add(playing);
+ }
+ }
+
+ /**
+ * Increase mRelayoutBlock, stopping relayout if mRelayoutBlock is now greater than 0.
+ */
+ public void incrementRelayoutBlock() {
+ mRelayoutBlock++;
+ }
+
static class Factory {
DesktopModeWindowDecoration create(