Loading core/java/android/view/InsetsController.java +24 −2 Original line number Diff line number Diff line Loading @@ -314,6 +314,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation (int) (startValue.right + fraction * (endValue.right - startValue.right)), (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 * animate insets. Loading @@ -330,6 +333,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private final long mDurationMs; private final boolean mDisable; private final int mFloatingImeBottomInset; private final WindowInsetsAnimationControlListener mLoggingListener; private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal = new ThreadLocal<AnimationHandler>() { Loading @@ -343,7 +347,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks, @InsetsType int requestedTypes, @Behavior int behavior, boolean disable, int floatingImeBottomInset) { int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener) { mShow = show; mHasAnimationCallbacks = hasAnimationCallbacks; mRequestedTypes = requestedTypes; Loading @@ -351,12 +355,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mDurationMs = calculateDurationMs(); mDisable = disable; mFloatingImeBottomInset = floatingImeBottomInset; mLoggingListener = loggingListener; } @Override public void onReady(WindowInsetsAnimationController controller, int types) { mController = controller; if (DEBUG) Log.d(TAG, "default animation onReady types: " + types); if (mLoggingListener != null) { mLoggingListener.onReady(controller, types); } if (mDisable) { onAnimationFinish(); Loading Loading @@ -410,6 +418,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public void onFinished(WindowInsetsAnimationController controller) { if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:" + Type.toString(mRequestedTypes)); if (mLoggingListener != null) { mLoggingListener.onFinished(controller); } } @Override Loading @@ -420,6 +431,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:" + mRequestedTypes); if (mLoggingListener != null) { mLoggingListener.onCancelled(controller); } } protected Interpolator getInsetsInterpolator() { Loading Loading @@ -1147,6 +1161,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation 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). */ Loading Loading @@ -1460,7 +1481,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); final InternalAnimationControlListener listener = new InternalAnimationControlListener( 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 // the controlled types should be animated regardless of the frame. Loading core/java/android/view/PendingInsetsController.java +15 −1 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ public class PendingInsetsController implements WindowInsetsController { private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners = new ArrayList<>(); private int mCaptionInsetsHeight = 0; private WindowInsetsAnimationControlListener mLoggingListener; @Override public void show(int types) { Loading Loading @@ -176,6 +177,9 @@ public class PendingInsetsController implements WindowInsetsController { controller.addOnControllableInsetsChangedListener( mControllableInsetsChangedListeners.get(i)); } if (mLoggingListener != null) { controller.setSystemDrivenInsetsAnimationLoggingListener(mLoggingListener); } // Reset all state so it doesn't get applied twice just in case mRequests.clear(); Loading @@ -184,7 +188,7 @@ public class PendingInsetsController implements WindowInsetsController { mAppearance = 0; mAppearanceMask = 0; mAnimationsDisabled = false; mLoggingListener = null; // After replaying, we forward everything directly to the replayed instance. mReplayedInsetsController = controller; } Loading @@ -197,6 +201,16 @@ public class PendingInsetsController implements WindowInsetsController { mReplayedInsetsController = null; } @Override public void setSystemDrivenInsetsAnimationLoggingListener( @Nullable WindowInsetsAnimationControlListener listener) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemDrivenInsetsAnimationLoggingListener(listener); } else { mLoggingListener = listener; } } @Override public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, @Nullable Interpolator interpolator, Loading core/java/android/view/WindowInsetsController.java +15 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,21 @@ public interface WindowInsetsController { @Nullable CancellationSignal cancellationSignal, @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. * <p> Loading core/tests/coretests/src/android/view/InsetsControllerTest.java +15 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,21 @@ public class InsetsControllerTest { 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 public void testAnimationEndState() { InsetsSourceControl[] controls = prepareControls(); Loading core/tests/coretests/src/android/view/PendingInsetsControllerTest.java +19 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,25 @@ public class PendingInsetsControllerTest { 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 public void testDetachReattach() { mPendingInsetsController.show(systemBars()); Loading Loading
core/java/android/view/InsetsController.java +24 −2 Original line number Diff line number Diff line Loading @@ -314,6 +314,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation (int) (startValue.right + fraction * (endValue.right - startValue.right)), (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 * animate insets. Loading @@ -330,6 +333,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private final long mDurationMs; private final boolean mDisable; private final int mFloatingImeBottomInset; private final WindowInsetsAnimationControlListener mLoggingListener; private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal = new ThreadLocal<AnimationHandler>() { Loading @@ -343,7 +347,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks, @InsetsType int requestedTypes, @Behavior int behavior, boolean disable, int floatingImeBottomInset) { int floatingImeBottomInset, WindowInsetsAnimationControlListener loggingListener) { mShow = show; mHasAnimationCallbacks = hasAnimationCallbacks; mRequestedTypes = requestedTypes; Loading @@ -351,12 +355,16 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation mDurationMs = calculateDurationMs(); mDisable = disable; mFloatingImeBottomInset = floatingImeBottomInset; mLoggingListener = loggingListener; } @Override public void onReady(WindowInsetsAnimationController controller, int types) { mController = controller; if (DEBUG) Log.d(TAG, "default animation onReady types: " + types); if (mLoggingListener != null) { mLoggingListener.onReady(controller, types); } if (mDisable) { onAnimationFinish(); Loading Loading @@ -410,6 +418,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation public void onFinished(WindowInsetsAnimationController controller) { if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onFinished types:" + Type.toString(mRequestedTypes)); if (mLoggingListener != null) { mLoggingListener.onFinished(controller); } } @Override Loading @@ -420,6 +431,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } if (DEBUG) Log.d(TAG, "InternalAnimationControlListener onCancelled types:" + mRequestedTypes); if (mLoggingListener != null) { mLoggingListener.onCancelled(controller); } } protected Interpolator getInsetsInterpolator() { Loading Loading @@ -1147,6 +1161,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation 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). */ Loading Loading @@ -1460,7 +1481,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); final InternalAnimationControlListener listener = new InternalAnimationControlListener( 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 // the controlled types should be animated regardless of the frame. Loading
core/java/android/view/PendingInsetsController.java +15 −1 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ public class PendingInsetsController implements WindowInsetsController { private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners = new ArrayList<>(); private int mCaptionInsetsHeight = 0; private WindowInsetsAnimationControlListener mLoggingListener; @Override public void show(int types) { Loading Loading @@ -176,6 +177,9 @@ public class PendingInsetsController implements WindowInsetsController { controller.addOnControllableInsetsChangedListener( mControllableInsetsChangedListeners.get(i)); } if (mLoggingListener != null) { controller.setSystemDrivenInsetsAnimationLoggingListener(mLoggingListener); } // Reset all state so it doesn't get applied twice just in case mRequests.clear(); Loading @@ -184,7 +188,7 @@ public class PendingInsetsController implements WindowInsetsController { mAppearance = 0; mAppearanceMask = 0; mAnimationsDisabled = false; mLoggingListener = null; // After replaying, we forward everything directly to the replayed instance. mReplayedInsetsController = controller; } Loading @@ -197,6 +201,16 @@ public class PendingInsetsController implements WindowInsetsController { mReplayedInsetsController = null; } @Override public void setSystemDrivenInsetsAnimationLoggingListener( @Nullable WindowInsetsAnimationControlListener listener) { if (mReplayedInsetsController != null) { mReplayedInsetsController.setSystemDrivenInsetsAnimationLoggingListener(listener); } else { mLoggingListener = listener; } } @Override public void controlWindowInsetsAnimation(@InsetsType int types, long durationMillis, @Nullable Interpolator interpolator, Loading
core/java/android/view/WindowInsetsController.java +15 −0 Original line number Diff line number Diff line Loading @@ -200,6 +200,21 @@ public interface WindowInsetsController { @Nullable CancellationSignal cancellationSignal, @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. * <p> Loading
core/tests/coretests/src/android/view/InsetsControllerTest.java +15 −0 Original line number Diff line number Diff line Loading @@ -235,6 +235,21 @@ public class InsetsControllerTest { 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 public void testAnimationEndState() { InsetsSourceControl[] controls = prepareControls(); Loading
core/tests/coretests/src/android/view/PendingInsetsControllerTest.java +19 −0 Original line number Diff line number Diff line Loading @@ -212,6 +212,25 @@ public class PendingInsetsControllerTest { 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 public void testDetachReattach() { mPendingInsetsController.show(systemBars()); Loading