Merge "Add passive callback for system-run insets animation" into tm-qpr-dev

This commit is contained in:
Hyunyoung Song
2022-08-19 18:37:40 +00:00
committed by Android (Google) Code Review
6 changed files with 89 additions and 4 deletions

View File

@@ -314,6 +314,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
(int) (startValue.right + fraction * (endValue.right - startValue.right)), (int) (startValue.right + fraction * (endValue.right - startValue.right)),
(int) (startValue.bottom + fraction * (endValue.bottom - startValue.bottom))); (int) (startValue.bottom + fraction * (endValue.bottom - startValue.bottom)));
/** Logging listener. */
private WindowInsetsAnimationControlListener mLoggingListener;
/** /**
* The default implementation of listener, to be used by InsetsController and InsetsPolicy to * The default implementation of listener, to be used by InsetsController and InsetsPolicy to
* animate insets. * animate insets.
@@ -330,6 +333,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private final long mDurationMs; private final long mDurationMs;
private final boolean mDisable; private final boolean mDisable;
private final int mFloatingImeBottomInset; private final int mFloatingImeBottomInset;
private final WindowInsetsAnimationControlListener mLoggingListener;
private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal = private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
new ThreadLocal<AnimationHandler>() { new ThreadLocal<AnimationHandler>() {
@@ -343,7 +347,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks, public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks,
@InsetsType int requestedTypes, @Behavior int behavior, boolean disable, @InsetsType int requestedTypes, @Behavior int behavior, boolean disable,
int floatingImeBottomInset) { int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener) {
mShow = show; mShow = show;
mHasAnimationCallbacks = hasAnimationCallbacks; mHasAnimationCallbacks = hasAnimationCallbacks;
mRequestedTypes = requestedTypes; mRequestedTypes = requestedTypes;
@@ -351,12 +355,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mDurationMs = calculateDurationMs(); mDurationMs = calculateDurationMs();
mDisable = disable; mDisable = disable;
mFloatingImeBottomInset = floatingImeBottomInset; mFloatingImeBottomInset = floatingImeBottomInset;
mLoggingListener = loggingListener;
} }
@Override @Override
public void onReady(WindowInsetsAnimationController controller, int types) { public void onReady(WindowInsetsAnimationController controller, int types) {
mController = controller; mController = controller;
if (DEBUG) Log.d(TAG, "default animation onReady types: " + types); if (DEBUG) Log.d(TAG, "default animation onReady types: " + types);
if (mLoggingListener != null) {
mLoggingListener.onReady(controller, types);
}
if (mDisable) { if (mDisable) {
onAnimationFinish(); onAnimationFinish();
@@ -410,6 +418,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
public void onFinished(WindowInsetsAnimationController controller) { public void onFinished(WindowInsetsAnimationController controller) {
if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:" if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:"
+ Type.toString(mRequestedTypes)); + Type.toString(mRequestedTypes));
if (mLoggingListener != null) {
mLoggingListener.onFinished(controller);
}
} }
@Override @Override
@@ -420,6 +431,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
} }
if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:" if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:"
+ mRequestedTypes); + mRequestedTypes);
if (mLoggingListener != null) {
mLoggingListener.onCancelled(controller);
}
} }
protected Interpolator getInsetsInterpolator() { protected Interpolator getInsetsInterpolator() {
@@ -1147,6 +1161,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
updateRequestedVisibilities(); updateRequestedVisibilities();
} }
// TODO(b/242962223): Make this setter restrictive.
@Override
public void setSystemDrivenInsetsAnimationLoggingListener(
@Nullable WindowInsetsAnimationControlListener listener) {
mLoggingListener = listener;
}
/** /**
* @return Pair of (types ready to animate, IME ready to animate). * @return Pair of (types ready to animate, IME ready to animate).
*/ */
@@ -1460,7 +1481,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks();
final InternalAnimationControlListener listener = new InternalAnimationControlListener( final InternalAnimationControlListener listener = new InternalAnimationControlListener(
show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(), show, hasAnimationCallbacks, types, mHost.getSystemBarsBehavior(),
skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP)); skipAnim || mAnimationsDisabled, mHost.dipToPx(FLOATING_IME_BOTTOM_INSET_DP),
mLoggingListener);
// We are about to playing the default animation (show/hide). Passing a null frame indicates // We are about to playing the default animation (show/hide). Passing a null frame indicates
// the controlled types should be animated regardless of the frame. // the controlled types should be animated regardless of the frame.

View File

@@ -44,6 +44,7 @@ public class PendingInsetsController implements WindowInsetsController {
private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
= new ArrayList<>(); = new ArrayList<>();
private int mCaptionInsetsHeight = 0; private int mCaptionInsetsHeight = 0;
private WindowInsetsAnimationControlListener mLoggingListener;
@Override @Override
public void show(int types) { public void show(int types) {
@@ -176,6 +177,9 @@ public class PendingInsetsController implements WindowInsetsController {
controller.addOnControllableInsetsChangedListener( controller.addOnControllableInsetsChangedListener(
mControllableInsetsChangedListeners.get(i)); mControllableInsetsChangedListeners.get(i));
} }
if (mLoggingListener != null) {
controller.setSystemDrivenInsetsAnimationLoggingListener(mLoggingListener);
}
// Reset all state so it doesn't get applied twice just in case // Reset all state so it doesn't get applied twice just in case
mRequests.clear(); mRequests.clear();
@@ -184,7 +188,7 @@ public class PendingInsetsController implements WindowInsetsController {
mAppearance = 0; mAppearance = 0;
mAppearanceMask = 0; mAppearanceMask = 0;
mAnimationsDisabled = false; mAnimationsDisabled = false;
mLoggingListener = null;
// After replaying, we forward everything directly to the replayed instance. // After replaying, we forward everything directly to the replayed instance.
mReplayedInsetsController = controller; mReplayedInsetsController = controller;
} }
@@ -197,6 +201,16 @@ public class PendingInsetsController implements WindowInsetsController {
mReplayedInsetsController = null; mReplayedInsetsController = null;
} }
@Override
public void setSystemDrivenInsetsAnimationLoggingListener(
@Nullable WindowInsetsAnimationControlListener listener) {
if (mReplayedInsetsController != null) {
mReplayedInsetsController.setSystemDrivenInsetsAnimationLoggingListener(listener);
} else {
mLoggingListener = listener;
}
}
@Override @Override
public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis,
@Nullable Interpolator interpolator, @Nullable Interpolator interpolator,

View File

@@ -200,6 +200,21 @@ public interface WindowInsetsController {
@Nullable CancellationSignal cancellationSignal, @Nullable CancellationSignal cancellationSignal,
@NonNull WindowInsetsAnimationControlListener listener); @NonNull WindowInsetsAnimationControlListener listener);
/**
* Lets the application add non-controllable listener object that can be called back
* when animation is invoked by the system by host calling methods such as {@link #show} or
* {@link #hide}.
*
* The listener is supposed to be used for logging only, using the control or
* relying on the timing of the callback in any other way is not supported.
*
* @param listener The {@link WindowInsetsAnimationControlListener} that gets called when
* the animation is driven by the system and not the host
* @hide
*/
void setSystemDrivenInsetsAnimationLoggingListener(
@Nullable WindowInsetsAnimationControlListener listener);
/** /**
* Controls the appearance of system bars. * Controls the appearance of system bars.
* <p> * <p>

View File

@@ -235,6 +235,21 @@ public class InsetsControllerTest {
verify(controlListener, never()).onReady(any(), anyInt()); verify(controlListener, never()).onReady(any(), anyInt());
} }
@Test
public void testSystemDrivenInsetsAnimationLoggingListener_onReady() {
prepareControls();
// only the original thread that created view hierarchy can touch its views
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
WindowInsetsAnimationControlListener loggingListener =
mock(WindowInsetsAnimationControlListener.class);
mController.setSystemDrivenInsetsAnimationLoggingListener(loggingListener);
mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
// since there is no focused view, forcefully make IME visible.
mController.show(Type.ime(), true /* fromIme */);
verify(loggingListener).onReady(notNull(), anyInt());
});
}
@Test @Test
public void testAnimationEndState() { public void testAnimationEndState() {
InsetsSourceControl[] controls = prepareControls(); InsetsSourceControl[] controls = prepareControls();

View File

@@ -212,6 +212,25 @@ public class PendingInsetsControllerTest {
verifyZeroInteractions(secondController); verifyZeroInteractions(secondController);
} }
@Test
public void testSystemDrivenInsetsAnimationLoggingListener() {
WindowInsetsAnimationControlListener listener =
mock(WindowInsetsAnimationControlListener.class);
mPendingInsetsController.setSystemDrivenInsetsAnimationLoggingListener(listener);
mPendingInsetsController.replayAndAttach(mReplayedController);
verify(mReplayedController).setSystemDrivenInsetsAnimationLoggingListener(eq(listener));
}
@Test
public void testSystemDrivenInsetsAnimationLoggingListener_direct() {
mPendingInsetsController.replayAndAttach(mReplayedController);
WindowInsetsAnimationControlListener listener =
mock(WindowInsetsAnimationControlListener.class);
mPendingInsetsController.setSystemDrivenInsetsAnimationLoggingListener(listener);
verify(mReplayedController).setSystemDrivenInsetsAnimationLoggingListener(
eq(listener));
}
@Test @Test
public void testDetachReattach() { public void testDetachReattach() {
mPendingInsetsController.show(systemBars()); mPendingInsetsController.show(systemBars());

View File

@@ -759,7 +759,7 @@ class InsetsPolicy {
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) { InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) {
super(show, false /* hasCallbacks */, types, BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE, super(show, false /* hasCallbacks */, types, BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE,
false /* disable */, 0 /* floatingImeBottomInsets */); false /* disable */, 0 /* floatingImeBottomInsets */, null);
mFinishCallback = finishCallback; mFinishCallback = finishCallback;
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this); mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
} }