summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginRemoteTransition.java15
-rw-r--r--packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginTransitionSession.java8
-rw-r--r--packages/SystemUI/animation/lib/src/com/android/systemui/animation/ViewUIComponent.java88
3 files changed, 92 insertions, 19 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 91fad4fb6dc2..56d85ab8aca0 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
@@ -107,7 +107,7 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
IBinder mergeTarget,
IRemoteTransitionFinishedCallback finishCallback) {
logD("mergeAnimation - " + info);
- mHandler.post(this::cancel);
+ cancel();
}
@Override
@@ -129,7 +129,7 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
@Override
public void onTransitionConsumed(IBinder transition, boolean aborted) {
logD("onTransitionConsumed - aborted: " + aborted);
- mHandler.post(this::cancel);
+ cancel();
}
private void startAnimationInternal(
@@ -342,11 +342,14 @@ public class OriginRemoteTransition extends IRemoteTransition.Stub {
mFinishCallback = null;
}
- private void cancel() {
+ public void cancel() {
logD("cancel()");
- if (mAnimator != null) {
- mAnimator.cancel();
- }
+ mHandler.post(
+ () -> {
+ if (mAnimator != null) {
+ mAnimator.cancel();
+ }
+ });
}
private static void logD(String msg) {
diff --git a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginTransitionSession.java b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginTransitionSession.java
index 6d6aa8895ed0..cb3dfb9e78e7 100644
--- a/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginTransitionSession.java
+++ b/packages/SystemUI/animation/lib/src/com/android/systemui/animation/OriginTransitionSession.java
@@ -43,6 +43,7 @@ import java.util.function.Supplier;
/**
* A session object that holds origin transition states for starting an activity from an on-screen
* UI component and smoothly transitioning back from the activity to the same UI component.
+ *
* @hide
*/
public class OriginTransitionSession {
@@ -143,6 +144,12 @@ public class OriginTransitionSession {
logE("Unable to cancel origin transition!", e);
}
}
+ if (mEntryTransition instanceof OriginRemoteTransition) {
+ ((OriginRemoteTransition) mEntryTransition).cancel();
+ }
+ if (mExitTransition instanceof OriginRemoteTransition) {
+ ((OriginRemoteTransition) mExitTransition).cancel();
+ }
}
private boolean hasEntryTransition() {
@@ -182,6 +189,7 @@ public class OriginTransitionSession {
/**
* A builder to build a {@link OriginTransitionSession}.
+ *
* @hide
*/
public static class Builder {
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 7c219c6ca921..2e8f92839fa6 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
@@ -24,13 +24,15 @@ import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Build;
+import android.os.Handler;
+import android.os.Looper;
import android.util.Log;
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 android.view.ViewTreeObserver;
import java.util.ArrayList;
import java.util.List;
@@ -51,8 +53,9 @@ public class ViewUIComponent implements UIComponent {
private final Path mClippingPath = new Path();
private final Outline mClippingOutline = new Outline();
- private final OnDrawListener mOnDrawListener = this::postDraw;
+ private final LifecycleListener mLifecycleListener = new LifecycleListener();
private final View mView;
+ private final Handler mMainHandler;
@Nullable private SurfaceControl mSurfaceControl;
@Nullable private Surface mSurface;
@@ -62,6 +65,7 @@ public class ViewUIComponent implements UIComponent {
public ViewUIComponent(View view) {
mView = view;
+ mMainHandler = new Handler(Looper.getMainLooper());
}
/**
@@ -110,11 +114,11 @@ public class ViewUIComponent implements UIComponent {
t.reparent(mSurfaceControl, transitionLeash).show(mSurfaceControl);
// Make sure view draw triggers surface draw.
- mView.getViewTreeObserver().addOnDrawListener(mOnDrawListener);
+ mLifecycleListener.register();
// Make the view invisible AFTER the surface is shown.
t.addTransactionCommittedListener(
- mView::post,
+ this::post,
() -> {
logD("Surface attached!");
forceDraw();
@@ -129,14 +133,14 @@ public class ViewUIComponent implements UIComponent {
SurfaceControl sc = mSurfaceControl;
mSurface = null;
mSurfaceControl = null;
- mView.getViewTreeObserver().removeOnDrawListener(mOnDrawListener);
+ mLifecycleListener.unregister();
// Restore view visibility
mView.setVisibility(mVisibleOverride ? View.VISIBLE : View.INVISIBLE);
// Clean up surfaces.
SurfaceControl.Transaction t = new SurfaceControl.Transaction();
t.reparent(sc, null)
.addTransactionCommittedListener(
- mView::post,
+ this::post,
() -> {
s.release();
sc.release();
@@ -269,7 +273,66 @@ public class ViewUIComponent implements UIComponent {
return;
}
mDirty = true;
- mView.post(this::draw);
+ post(this::draw);
+ }
+
+ private void post(Runnable r) {
+ if (mView.isAttachedToWindow()) {
+ mView.post(r);
+ } else {
+ // If the view is detached from window, {@code View.post()} will postpone the action
+ // until the view is attached again. However, we don't know if the view will be attached
+ // again, so we post the action to the main thread in this case. This could lead to race
+ // condition if the attachment change caused a thread switching, and it's the caller's
+ // responsibility to ensure the window attachment state doesn't change unexpectedly.
+ if (DEBUG) {
+ Log.w(TAG, mView + " is not attached. Posting action to main thread!");
+ }
+ mMainHandler.post(r);
+ }
+ }
+
+ /** A listener for monitoring view life cycles. */
+ private class LifecycleListener
+ implements ViewTreeObserver.OnDrawListener, View.OnAttachStateChangeListener {
+ private boolean mRegistered;
+
+ @Override
+ public void onDraw() {
+ // View draw should trigger surface draw.
+ postDraw();
+ }
+
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ // empty
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {
+ Log.w(
+ TAG,
+ v + " is detached from the window. Unregistering the life cycle listener ...");
+ unregister();
+ }
+
+ public void register() {
+ if (mRegistered) {
+ return;
+ }
+ mRegistered = true;
+ mView.getViewTreeObserver().addOnDrawListener(this);
+ mView.addOnAttachStateChangeListener(this);
+ }
+
+ public void unregister() {
+ if (!mRegistered) {
+ return;
+ }
+ mRegistered = false;
+ mView.getViewTreeObserver().removeOnDrawListener(this);
+ mView.removeOnAttachStateChangeListener(this);
+ }
}
/** @hide */
@@ -278,34 +341,33 @@ public class ViewUIComponent implements UIComponent {
@Override
public Transaction setAlpha(ViewUIComponent ui, float alpha) {
- mChanges.add(() -> ui.mView.post(() -> ui.setAlpha(alpha)));
+ mChanges.add(() -> ui.post(() -> ui.setAlpha(alpha)));
return this;
}
@Override
public Transaction setVisible(ViewUIComponent ui, boolean visible) {
- mChanges.add(() -> ui.mView.post(() -> ui.setVisible(visible)));
+ mChanges.add(() -> ui.post(() -> ui.setVisible(visible)));
return this;
}
@Override
public Transaction setBounds(ViewUIComponent ui, Rect bounds) {
- mChanges.add(() -> ui.mView.post(() -> ui.setBounds(bounds)));
+ mChanges.add(() -> ui.post(() -> ui.setBounds(bounds)));
return this;
}
@Override
public Transaction attachToTransitionLeash(
ViewUIComponent ui, SurfaceControl transitionLeash, int w, int h) {
- mChanges.add(
- () -> ui.mView.post(() -> ui.attachToTransitionLeash(transitionLeash, w, h)));
+ mChanges.add(() -> ui.post(() -> ui.attachToTransitionLeash(transitionLeash, w, h)));
return this;
}
@Override
public Transaction detachFromTransitionLeash(
ViewUIComponent ui, Executor executor, Runnable onDone) {
- mChanges.add(() -> ui.mView.post(() -> ui.detachFromTransitionLeash(executor, onDone)));
+ mChanges.add(() -> ui.post(() -> ui.detachFromTransitionLeash(executor, onDone)));
return this;
}