Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +7 −11 Original line number Diff line number Diff line Loading @@ -115,7 +115,6 @@ public class BubbleBarController extends IBubblesListener.Stub { private BubbleBarItem mSelectedBubble; private TaskbarSharedState mSharedState; private ImeVisibilityChecker mImeVisibilityChecker; private BubbleBarViewController mBubbleBarViewController; private BubbleStashController mBubbleStashController; private Optional<BubbleStashedHandleViewController> mBubbleStashedHandleViewController; Loading @@ -126,6 +125,8 @@ public class BubbleBarController extends IBubblesListener.Stub { // Cache last sent top coordinate to avoid sending duplicate updates to shell private int mLastSentBubbleBarTop; private boolean mIsImeVisible = false; /** * Similar to {@link BubbleBarUpdate} but rather than {@link BubbleInfo}s it uses * {@link BubbleBarBubble}s so that it can be used to update the views. Loading Loading @@ -192,10 +193,8 @@ public class BubbleBarController extends IBubblesListener.Stub { /** Initializes controllers. */ public void init(BubbleControllers bubbleControllers, BubbleBarLocationListener bubbleBarLocationListener, ImeVisibilityChecker imeVisibilityChecker, TaskbarSharedState sharedState) { mSharedState = sharedState; mImeVisibilityChecker = imeVisibilityChecker; mBubbleBarViewController = bubbleControllers.bubbleBarViewController; mBubbleStashController = bubbleControllers.bubbleStashController; mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController; Loading Loading @@ -234,6 +233,10 @@ public class BubbleBarController extends IBubblesListener.Stub { boolean sysuiLocked = (flags & MASK_SYSUI_LOCKED) != 0; mBubbleStashController.setSysuiLocked(sysuiLocked); mIsImeVisible = (flags & SYSUI_STATE_IME_SHOWING) != 0; if (mIsImeVisible) { mBubbleBarViewController.onImeVisible(); } } // Loading Loading @@ -309,8 +312,7 @@ public class BubbleBarController extends IBubblesListener.Stub { // enabling gesture nav. also suppress animation if the bubble bar is hidden for sysui e.g. // the shade is open, or we're locked. final boolean suppressAnimation = update.initialState || mBubbleBarViewController.isHiddenForSysui() || mImeVisibilityChecker.isImeVisible(); update.initialState || mBubbleBarViewController.isHiddenForSysui() || mIsImeVisible; if (update.initialState && mSharedState.hasSavedBubbles()) { // clear restored state Loading Loading @@ -572,12 +574,6 @@ public class BubbleBarController extends IBubblesListener.Stub { mBubbleBarViewController.addBubble(bubble, isExpanding, suppressAnimation); } /** Interface for checking whether the IME is visible. */ public interface ImeVisibilityChecker { /** Whether the IME is visible. */ boolean isImeVisible(); } /** Listener of {@link BubbleBarLocation} updates. */ public interface BubbleBarLocationListener { Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +7 −0 Original line number Diff line number Diff line Loading @@ -391,6 +391,13 @@ public class BubbleBarViewController { } } /** Notifies that the IME became visible. */ public void onImeVisible() { if (isAnimatingNewBubble()) { mBubbleBarViewAnimator.interruptForIme(); } } // // The below animators are exposed to BubbleStashController so it can manage the stashing // animation. Loading quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java +0 −1 Original line number Diff line number Diff line Loading @@ -89,7 +89,6 @@ public class BubbleControllers { ); bubbleBarController.init(this, bubbleBarLocationListeners, taskbarControllers.navbarButtonsViewController::isImeVisible, taskbarSharedState); bubbleStashedHandleViewController.ifPresent( controller -> controller.init(/* bubbleControllers = */ this)); Loading quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt +15 −0 Original line number Diff line number Diff line Loading @@ -532,6 +532,21 @@ constructor( ) } /** Interrupts the animation due to the IME becoming visible. */ fun interruptForIme() { cancelFlyout() val hideAnimation = animatingBubble?.hideAnimation ?: return scheduler.cancel(hideAnimation) animatingBubble = null bubbleStashController.getStashedHandlePhysicsAnimator().cancelIfRunning() bubbleBarView.relativePivotY = 1f // stash the bubble bar since the IME is now visible bubbleStashController.onNewBubbleAnimationInterrupted( /* isStashed= */ true, bubbleBarView.translationY, ) } fun expandedWhileAnimating() { val animatingBubble = animatingBubble ?: return this.animatingBubble = animatingBubble.copy(expand = true) Loading quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt +45 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever Loading Loading @@ -1266,6 +1267,50 @@ class BubbleBarViewAnimatorTest { verify(bubbleStashController).stashBubbleBarImmediate() } @Test fun interruptForIme() { setUpBubbleBar() setUpBubbleStashController() val handle = View(context) val handleAnimator = PhysicsAnimator.getInstance(handle) whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator) val animator = BubbleBarViewAnimator( bubbleBarView, bubbleStashController, flyoutController, onExpandedNoOp, animatorScheduler, ) InstrumentationRegistry.getInstrumentation().runOnMainSync { animator.animateBubbleInForStashed(bubble, isExpanding = false) } // wait for the animation to start InstrumentationRegistry.getInstrumentation().runOnMainSync {} PhysicsAnimatorTestUtils.blockUntilFirstAnimationFrameWhereTrue(handleAnimator) { true } handleAnimator.assertIsRunning() assertThat(animator.isAnimating).isTrue() // verify the hide bubble animation is pending assertThat(animatorScheduler.delayedBlock).isNotNull() InstrumentationRegistry.getInstrumentation().runOnMainSync { animator.interruptForIme() } // verify that the hide animation was canceled assertThat(animatorScheduler.delayedBlock).isNull() assertThat(animator.isAnimating).isFalse() verify(bubbleStashController).onNewBubbleAnimationInterrupted(eq(true), any()) // PhysicsAnimatorTestUtils posts the cancellation to the main thread so we need to wait // again InstrumentationRegistry.getInstrumentation().waitForIdleSync() handleAnimator.assertIsNotRunning() } private fun setUpBubbleBar() { bubbleBarView = BubbleBarView(context) InstrumentationRegistry.getInstrumentation().runOnMainSync { Loading Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarController.java +7 −11 Original line number Diff line number Diff line Loading @@ -115,7 +115,6 @@ public class BubbleBarController extends IBubblesListener.Stub { private BubbleBarItem mSelectedBubble; private TaskbarSharedState mSharedState; private ImeVisibilityChecker mImeVisibilityChecker; private BubbleBarViewController mBubbleBarViewController; private BubbleStashController mBubbleStashController; private Optional<BubbleStashedHandleViewController> mBubbleStashedHandleViewController; Loading @@ -126,6 +125,8 @@ public class BubbleBarController extends IBubblesListener.Stub { // Cache last sent top coordinate to avoid sending duplicate updates to shell private int mLastSentBubbleBarTop; private boolean mIsImeVisible = false; /** * Similar to {@link BubbleBarUpdate} but rather than {@link BubbleInfo}s it uses * {@link BubbleBarBubble}s so that it can be used to update the views. Loading Loading @@ -192,10 +193,8 @@ public class BubbleBarController extends IBubblesListener.Stub { /** Initializes controllers. */ public void init(BubbleControllers bubbleControllers, BubbleBarLocationListener bubbleBarLocationListener, ImeVisibilityChecker imeVisibilityChecker, TaskbarSharedState sharedState) { mSharedState = sharedState; mImeVisibilityChecker = imeVisibilityChecker; mBubbleBarViewController = bubbleControllers.bubbleBarViewController; mBubbleStashController = bubbleControllers.bubbleStashController; mBubbleStashedHandleViewController = bubbleControllers.bubbleStashedHandleViewController; Loading Loading @@ -234,6 +233,10 @@ public class BubbleBarController extends IBubblesListener.Stub { boolean sysuiLocked = (flags & MASK_SYSUI_LOCKED) != 0; mBubbleStashController.setSysuiLocked(sysuiLocked); mIsImeVisible = (flags & SYSUI_STATE_IME_SHOWING) != 0; if (mIsImeVisible) { mBubbleBarViewController.onImeVisible(); } } // Loading Loading @@ -309,8 +312,7 @@ public class BubbleBarController extends IBubblesListener.Stub { // enabling gesture nav. also suppress animation if the bubble bar is hidden for sysui e.g. // the shade is open, or we're locked. final boolean suppressAnimation = update.initialState || mBubbleBarViewController.isHiddenForSysui() || mImeVisibilityChecker.isImeVisible(); update.initialState || mBubbleBarViewController.isHiddenForSysui() || mIsImeVisible; if (update.initialState && mSharedState.hasSavedBubbles()) { // clear restored state Loading Loading @@ -572,12 +574,6 @@ public class BubbleBarController extends IBubblesListener.Stub { mBubbleBarViewController.addBubble(bubble, isExpanding, suppressAnimation); } /** Interface for checking whether the IME is visible. */ public interface ImeVisibilityChecker { /** Whether the IME is visible. */ boolean isImeVisible(); } /** Listener of {@link BubbleBarLocation} updates. */ public interface BubbleBarLocationListener { Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java +7 −0 Original line number Diff line number Diff line Loading @@ -391,6 +391,13 @@ public class BubbleBarViewController { } } /** Notifies that the IME became visible. */ public void onImeVisible() { if (isAnimatingNewBubble()) { mBubbleBarViewAnimator.interruptForIme(); } } // // The below animators are exposed to BubbleStashController so it can manage the stashing // animation. Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleControllers.java +0 −1 Original line number Diff line number Diff line Loading @@ -89,7 +89,6 @@ public class BubbleControllers { ); bubbleBarController.init(this, bubbleBarLocationListeners, taskbarControllers.navbarButtonsViewController::isImeVisible, taskbarSharedState); bubbleStashedHandleViewController.ifPresent( controller -> controller.init(/* bubbleControllers = */ this)); Loading
quickstep/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimator.kt +15 −0 Original line number Diff line number Diff line Loading @@ -532,6 +532,21 @@ constructor( ) } /** Interrupts the animation due to the IME becoming visible. */ fun interruptForIme() { cancelFlyout() val hideAnimation = animatingBubble?.hideAnimation ?: return scheduler.cancel(hideAnimation) animatingBubble = null bubbleStashController.getStashedHandlePhysicsAnimator().cancelIfRunning() bubbleBarView.relativePivotY = 1f // stash the bubble bar since the IME is now visible bubbleStashController.onNewBubbleAnimationInterrupted( /* isStashed= */ true, bubbleBarView.translationY, ) } fun expandedWhileAnimating() { val animatingBubble = animatingBubble ?: return this.animatingBubble = animatingBubble.copy(expand = true) Loading
quickstep/tests/multivalentTests/src/com/android/launcher3/taskbar/bubbles/animation/BubbleBarViewAnimatorTest.kt +45 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import org.junit.Test import org.junit.runner.RunWith import org.mockito.kotlin.any import org.mockito.kotlin.atLeastOnce import org.mockito.kotlin.eq import org.mockito.kotlin.mock import org.mockito.kotlin.verify import org.mockito.kotlin.whenever Loading Loading @@ -1266,6 +1267,50 @@ class BubbleBarViewAnimatorTest { verify(bubbleStashController).stashBubbleBarImmediate() } @Test fun interruptForIme() { setUpBubbleBar() setUpBubbleStashController() val handle = View(context) val handleAnimator = PhysicsAnimator.getInstance(handle) whenever(bubbleStashController.getStashedHandlePhysicsAnimator()).thenReturn(handleAnimator) val animator = BubbleBarViewAnimator( bubbleBarView, bubbleStashController, flyoutController, onExpandedNoOp, animatorScheduler, ) InstrumentationRegistry.getInstrumentation().runOnMainSync { animator.animateBubbleInForStashed(bubble, isExpanding = false) } // wait for the animation to start InstrumentationRegistry.getInstrumentation().runOnMainSync {} PhysicsAnimatorTestUtils.blockUntilFirstAnimationFrameWhereTrue(handleAnimator) { true } handleAnimator.assertIsRunning() assertThat(animator.isAnimating).isTrue() // verify the hide bubble animation is pending assertThat(animatorScheduler.delayedBlock).isNotNull() InstrumentationRegistry.getInstrumentation().runOnMainSync { animator.interruptForIme() } // verify that the hide animation was canceled assertThat(animatorScheduler.delayedBlock).isNull() assertThat(animator.isAnimating).isFalse() verify(bubbleStashController).onNewBubbleAnimationInterrupted(eq(true), any()) // PhysicsAnimatorTestUtils posts the cancellation to the main thread so we need to wait // again InstrumentationRegistry.getInstrumentation().waitForIdleSync() handleAnimator.assertIsNotRunning() } private fun setUpBubbleBar() { bubbleBarView = BubbleBarView(context) InstrumentationRegistry.getInstrumentation().runOnMainSync { Loading