summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Josh Yang <yzj@google.com> 2025-01-03 12:17:45 -0800
committer Josh Yang <yzj@google.com> 2025-01-03 12:25:00 -0800
commitefee0571730e4cfeb6902d232d02f7883f40292e (patch)
tree66fc03ead0009e9aa39e40ba230abf19b3e87911
parent6d8ad4dbec052d6327b5c96e82b58d6da8a5ed64 (diff)
Add a 100ms timeout when waiting for animation finish.
Also improve ViewUIComponent's detach flow. Flag: EXEMPTED - bug fix Test: manual test Change-Id: Iedf747f1a039bfb06be36cc0c3ebaa9125943a51
-rw-r--r--packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java50
-rw-r--r--packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java14
2 files changed, 52 insertions, 12 deletions
diff --git a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java
index 7d27a562f536..91fad4fb6dc2 100644
--- a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java
+++ b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java
@@ -43,6 +43,7 @@ import com.android.wm.shell.shared.TransitionUtil;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* An implementation of {@link IRemoteTransition} that accepts a {@link UIComponent} as the origin
@@ -52,6 +53,7 @@ import java.util.List;
*/
public class OriginRemoteTransition extends IRemoteTransition.Stub {
private static final String TAG = "OriginRemoteTransition";
+ private static final long FINISH_ANIMATION_TIMEOUT_MS = 100;
private final Context mContext;
private final boolean mIsEntry;
@@ -248,23 +250,20 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
if (mIsEntry) {
if (!closingSurfaces.isEmpty()) {
- tmpTransaction
- .setRelativeLayer(mOriginLeash, closingSurfaces.get(0), 1);
+ tmpTransaction.setRelativeLayer(mOriginLeash, closingSurfaces.get(0), 1);
} else {
logW("Missing closing surface is entry transition");
}
if (!openingSurfaces.isEmpty()) {
- tmpTransaction
- .setRelativeLayer(
- openingSurfaces.get(openingSurfaces.size() - 1), mOriginLeash, 1);
+ tmpTransaction.setRelativeLayer(
+ openingSurfaces.get(openingSurfaces.size() - 1), mOriginLeash, 1);
} else {
logW("Missing opening surface is entry transition");
}
} else {
if (!openingSurfaces.isEmpty()) {
- tmpTransaction
- .setRelativeLayer(mOriginLeash, openingSurfaces.get(0), 1);
+ tmpTransaction.setRelativeLayer(mOriginLeash, openingSurfaces.get(0), 1);
} else {
logW("Missing opening surface is exit transition");
}
@@ -293,12 +292,26 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
private void finishAnimation(boolean finished) {
logD("finishAnimation: finished=" + finished);
+ OneShotRunnable finishInternalRunnable = new OneShotRunnable(this::finishInternal);
+ Runnable timeoutRunnable =
+ () -> {
+ Log.w(TAG, "Timeout waiting for surface transaction!");
+ finishInternalRunnable.run();
+ };
+ Runnable committedRunnable =
+ () -> {
+ // Remove the timeout runnable.
+ mHandler.removeCallbacks(timeoutRunnable);
+ finishInternalRunnable.run();
+ };
if (mAnimator == null) {
// The transition didn't start. Ensure we apply the start transaction and report
// finish afterwards.
mStartTransaction
- .addTransactionCommittedListener(mHandler::post, this::finishInternal)
+ .addTransactionCommittedListener(mHandler::post, committedRunnable::run)
.apply();
+ // Call finishInternal() anyway after the timeout.
+ mHandler.postDelayed(timeoutRunnable, FINISH_ANIMATION_TIMEOUT_MS);
return;
}
mAnimator = null;
@@ -306,8 +319,10 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
mPlayer.onEnd(finished);
// Detach the origin from the transition leash and report finish after it's done.
mOriginTransaction
- .detachFromTransitionLeash(mOrigin, mHandler::post, this::finishInternal)
+ .detachFromTransitionLeash(mOrigin, mHandler::post, committedRunnable)
.commit();
+ // Call finishInternal() anyway after the timeout.
+ mHandler.postDelayed(timeoutRunnable, FINISH_ANIMATION_TIMEOUT_MS);
}
private void finishInternal() {
@@ -423,6 +438,23 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
return out;
}
+ /** A {@link Runnable} that will only run once. */
+ private static class OneShotRunnable implements Runnable {
+ private final AtomicBoolean mDone = new AtomicBoolean();
+ private final Runnable mRunnable;
+
+ OneShotRunnable(Runnable runnable) {
+ this.mRunnable = runnable;
+ }
+
+ @Override
+ public void run() {
+ if (!mDone.getAndSet(true)) {
+ mRunnable.run();
+ }
+ }
+ }
+
/**
* An interface that represents an origin transitions.
*
diff --git a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java
index d0404ec02306..7c219c6ca921 100644
--- a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java
+++ b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java
@@ -29,6 +29,7 @@ import android.view.Surface;
import android.view.SurfaceControl;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewRootImpl;
import android.view.ViewTreeObserver.OnDrawListener;
import java.util.ArrayList;
@@ -131,7 +132,6 @@ public class ViewUIComponent implements UIComponent {
mView.getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
// Restore view visibility
mView.setVisibility(mVisibleOverride ? View.VISIBLE : View.INVISIBLE);
- mView.invalidate();
// Clean up surfaces.
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
t.reparent(sc, null)
@@ -142,8 +142,16 @@ public class ViewUIComponent implements UIComponent {
sc.release();
executor.execute(onDone);
});
- // Apply transaction AFTER the view is drawn.
- mView.getRootSurfaceControl().applyTransactionOnDraw(t);
+ ViewRootImpl viewRoot = mView.getViewRootImpl();
+ if (viewRoot == null) {
+ t.apply();
+ } else {
+ // Apply transaction AFTER the view is drawn.
+ viewRoot.applyTransactionOnDraw(t);
+ // Request layout to force redrawing the entire view tree, so that the transaction is
+ // guaranteed to be applied.
+ viewRoot.requestLayout();
+ }
}
@Override