Loading libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt +137 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit Loading Loading @@ -174,6 +176,137 @@ class BubbleStackViewTest { assertThat(lastUpdate!!.expanded).isTrue() } @Test fun expandStack_imeHidden() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } assertThat(bubbleStackViewManager.onImeHidden).isNull() } @Test fun collapseStack_imeHidden() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } assertThat(bubbleStackViewManager.onImeHidden).isNull() InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to collapse the stack bubbleStackView.isExpanded = false verify(sysuiProxy).onStackExpandChanged(false) shellExecutor.flushAll() } assertThat(bubbleStackViewManager.onImeHidden).isNull() } @Test fun expandStack_waitsForIme() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(true, 100) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true } val onImeHidden = bubbleStackViewManager.onImeHidden assertThat(onImeHidden).isNotNull() verify(sysuiProxy, never()).onStackExpandChanged(any()) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { onImeHidden!!.run() verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } } @Test fun collapseStack_waitsForIme() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(true, 100) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true } var onImeHidden = bubbleStackViewManager.onImeHidden assertThat(onImeHidden).isNotNull() verify(sysuiProxy, never()).onStackExpandChanged(any()) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { onImeHidden!!.run() verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } bubbleStackViewManager.onImeHidden = null positioner.setImeVisible(true, 100) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to collapse the stack bubbleStackView.isExpanded = false } onImeHidden = bubbleStackViewManager.onImeHidden assertThat(onImeHidden).isNotNull() verify(sysuiProxy, never()).onStackExpandChanged(false) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { onImeHidden!!.run() verify(sysuiProxy).onStackExpandChanged(false) shellExecutor.flushAll() } } @Test fun tapDifferentBubble_shouldReorder() { val bubble1 = createAndInflateChatBubble(key = "bubble1") Loading Loading @@ -418,6 +551,7 @@ class BubbleStackViewTest { } private class FakeBubbleStackViewManager : BubbleStackViewManager { var onImeHidden: Runnable? = null override fun onAllBubblesAnimatedOut() {} Loading @@ -425,6 +559,8 @@ class BubbleStackViewTest { override fun checkNotificationPanelExpandedState(callback: Consumer<Boolean>) {} override fun hideCurrentInputMethod() {} override fun hideCurrentInputMethod(onImeHidden: Runnable?) { this.onImeHidden = onImeHidden } } } libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +9 −2 Original line number Diff line number Diff line Loading @@ -215,6 +215,8 @@ public class BubbleController implements ConfigurationChangeListener, private final BubblePositioner mBubblePositioner; private Bubbles.SysuiProxy mSysuiProxy; @Nullable private Runnable mOnImeHidden; // Tracks the id of the current (foreground) user. private int mCurrentUserId; // Current profiles of the user (e.g. user with a workprofile) Loading Loading @@ -615,7 +617,8 @@ public class BubbleController implements ConfigurationChangeListener, /** * Hides the current input method, wherever it may be focused, via InputMethodManagerInternal. */ void hideCurrentInputMethod() { void hideCurrentInputMethod(@Nullable Runnable onImeHidden) { mOnImeHidden = onImeHidden; mBubblePositioner.setImeVisible(false /* visible */, 0 /* height */); int displayId = mWindowManager.getDefaultDisplay().getDisplayId(); try { Loading Loading @@ -2267,7 +2270,7 @@ public class BubbleController implements ConfigurationChangeListener, if (mLayerView != null && mLayerView.isExpanded()) { if (mBubblePositioner.isImeVisible()) { // If we're collapsing, hide the IME hideCurrentInputMethod(); hideCurrentInputMethod(null); } mLayerView.collapse(); } Loading Loading @@ -2552,6 +2555,10 @@ public class BubbleController implements ConfigurationChangeListener, mBubblePositioner.setImeVisible(imeVisible, totalImeHeight); if (mStackView != null) { mStackView.setImeVisible(imeVisible); if (!imeVisible && mOnImeHidden != null) { mOnImeHidden.run(); mOnImeHidden = null; } } } Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedViewManager.kt +1 −1 Original line number Diff line number Diff line Loading @@ -82,7 +82,7 @@ interface BubbleExpandedViewManager { override fun isShowingAsBubbleBar(): Boolean = controller.isShowingAsBubbleBar override fun hideCurrentInputMethod() { controller.hideCurrentInputMethod() controller.hideCurrentInputMethod(null) } override fun updateBubbleBarLocation( Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +42 −21 Original line number Diff line number Diff line Loading @@ -2233,19 +2233,22 @@ public class BubbleStackView extends FrameLayout boolean wasExpanded = mIsExpanded; hideCurrentInputMethod(); // Do the actual expansion/collapse after the IME is hidden if it's currently visible in // order to avoid flickers Runnable onImeHidden = () -> { mSysuiProxyProvider.getSysuiProxy().onStackExpandChanged(shouldExpand); if (wasExpanded) { stopMonitoringSwipeUpGesture(); animateCollapse(); showManageMenu(false); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); } else { animateExpansion(); // TODO: move next line to BubbleData logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED); mManager.checkNotificationPanelExpandedState(notifPanelExpanded -> { Loading @@ -2256,6 +2259,14 @@ public class BubbleStackView extends FrameLayout } notifyExpansionChanged(mExpandedBubble, mIsExpanded); announceExpandForAccessibility(mExpandedBubble, mIsExpanded); }; if (mPositioner.isImeVisible()) { hideCurrentInputMethod(onImeHidden); } else { // the IME is already hidden, so run the runnable immediately onImeHidden.run(); } } /** Loading Loading @@ -2373,7 +2384,17 @@ public class BubbleStackView extends FrameLayout * not. */ void hideCurrentInputMethod() { mManager.hideCurrentInputMethod(); mManager.hideCurrentInputMethod(null); } /** * Hides the IME similar to {@link #hideCurrentInputMethod()} but also runs {@code onImeHidden} * after after the IME is hidden. * * @see #hideCurrentInputMethod() */ void hideCurrentInputMethod(Runnable onImeHidden) { mManager.hideCurrentInputMethod(onImeHidden); } /** Set the stack position to whatever the positioner says. */ Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackViewManager.kt +3 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ interface BubbleStackViewManager { fun checkNotificationPanelExpandedState(callback: Consumer<Boolean>) /** Requests to hide the current input method. */ fun hideCurrentInputMethod() fun hideCurrentInputMethod(onImeHidden: Runnable?) companion object { Loading @@ -52,8 +52,8 @@ interface BubbleStackViewManager { controller.isNotificationPanelExpanded(callback) } override fun hideCurrentInputMethod() { controller.hideCurrentInputMethod() override fun hideCurrentInputMethod(onImeHidden: Runnable?) { controller.hideCurrentInputMethod(onImeHidden) } } } Loading Loading
libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleStackViewTest.kt +137 −1 Original line number Diff line number Diff line Loading @@ -49,7 +49,9 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mockito import org.mockito.kotlin.any import org.mockito.kotlin.mock import org.mockito.kotlin.never import org.mockito.kotlin.verify import java.util.concurrent.Semaphore import java.util.concurrent.TimeUnit Loading Loading @@ -174,6 +176,137 @@ class BubbleStackViewTest { assertThat(lastUpdate!!.expanded).isTrue() } @Test fun expandStack_imeHidden() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } assertThat(bubbleStackViewManager.onImeHidden).isNull() } @Test fun collapseStack_imeHidden() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } assertThat(bubbleStackViewManager.onImeHidden).isNull() InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to collapse the stack bubbleStackView.isExpanded = false verify(sysuiProxy).onStackExpandChanged(false) shellExecutor.flushAll() } assertThat(bubbleStackViewManager.onImeHidden).isNull() } @Test fun expandStack_waitsForIme() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(true, 100) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true } val onImeHidden = bubbleStackViewManager.onImeHidden assertThat(onImeHidden).isNotNull() verify(sysuiProxy, never()).onStackExpandChanged(any()) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { onImeHidden!!.run() verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } } @Test fun collapseStack_waitsForIme() { val bubble = createAndInflateBubble() InstrumentationRegistry.getInstrumentation().runOnMainSync { bubbleStackView.addBubble(bubble) } InstrumentationRegistry.getInstrumentation().waitForIdleSync() assertThat(bubbleStackView.bubbleCount).isEqualTo(1) positioner.setImeVisible(true, 100) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to expand the stack bubbleStackView.isExpanded = true } var onImeHidden = bubbleStackViewManager.onImeHidden assertThat(onImeHidden).isNotNull() verify(sysuiProxy, never()).onStackExpandChanged(any()) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { onImeHidden!!.run() verify(sysuiProxy).onStackExpandChanged(true) shellExecutor.flushAll() } bubbleStackViewManager.onImeHidden = null positioner.setImeVisible(true, 100) InstrumentationRegistry.getInstrumentation().runOnMainSync { // simulate a request from the bubble data listener to collapse the stack bubbleStackView.isExpanded = false } onImeHidden = bubbleStackViewManager.onImeHidden assertThat(onImeHidden).isNotNull() verify(sysuiProxy, never()).onStackExpandChanged(false) positioner.setImeVisible(false, 0) InstrumentationRegistry.getInstrumentation().runOnMainSync { onImeHidden!!.run() verify(sysuiProxy).onStackExpandChanged(false) shellExecutor.flushAll() } } @Test fun tapDifferentBubble_shouldReorder() { val bubble1 = createAndInflateChatBubble(key = "bubble1") Loading Loading @@ -418,6 +551,7 @@ class BubbleStackViewTest { } private class FakeBubbleStackViewManager : BubbleStackViewManager { var onImeHidden: Runnable? = null override fun onAllBubblesAnimatedOut() {} Loading @@ -425,6 +559,8 @@ class BubbleStackViewTest { override fun checkNotificationPanelExpandedState(callback: Consumer<Boolean>) {} override fun hideCurrentInputMethod() {} override fun hideCurrentInputMethod(onImeHidden: Runnable?) { this.onImeHidden = onImeHidden } } }
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +9 −2 Original line number Diff line number Diff line Loading @@ -215,6 +215,8 @@ public class BubbleController implements ConfigurationChangeListener, private final BubblePositioner mBubblePositioner; private Bubbles.SysuiProxy mSysuiProxy; @Nullable private Runnable mOnImeHidden; // Tracks the id of the current (foreground) user. private int mCurrentUserId; // Current profiles of the user (e.g. user with a workprofile) Loading Loading @@ -615,7 +617,8 @@ public class BubbleController implements ConfigurationChangeListener, /** * Hides the current input method, wherever it may be focused, via InputMethodManagerInternal. */ void hideCurrentInputMethod() { void hideCurrentInputMethod(@Nullable Runnable onImeHidden) { mOnImeHidden = onImeHidden; mBubblePositioner.setImeVisible(false /* visible */, 0 /* height */); int displayId = mWindowManager.getDefaultDisplay().getDisplayId(); try { Loading Loading @@ -2267,7 +2270,7 @@ public class BubbleController implements ConfigurationChangeListener, if (mLayerView != null && mLayerView.isExpanded()) { if (mBubblePositioner.isImeVisible()) { // If we're collapsing, hide the IME hideCurrentInputMethod(); hideCurrentInputMethod(null); } mLayerView.collapse(); } Loading Loading @@ -2552,6 +2555,10 @@ public class BubbleController implements ConfigurationChangeListener, mBubblePositioner.setImeVisible(imeVisible, totalImeHeight); if (mStackView != null) { mStackView.setImeVisible(imeVisible); if (!imeVisible && mOnImeHidden != null) { mOnImeHidden.run(); mOnImeHidden = null; } } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleExpandedViewManager.kt +1 −1 Original line number Diff line number Diff line Loading @@ -82,7 +82,7 @@ interface BubbleExpandedViewManager { override fun isShowingAsBubbleBar(): Boolean = controller.isShowingAsBubbleBar override fun hideCurrentInputMethod() { controller.hideCurrentInputMethod() controller.hideCurrentInputMethod(null) } override fun updateBubbleBarLocation( Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackView.java +42 −21 Original line number Diff line number Diff line Loading @@ -2233,19 +2233,22 @@ public class BubbleStackView extends FrameLayout boolean wasExpanded = mIsExpanded; hideCurrentInputMethod(); // Do the actual expansion/collapse after the IME is hidden if it's currently visible in // order to avoid flickers Runnable onImeHidden = () -> { mSysuiProxyProvider.getSysuiProxy().onStackExpandChanged(shouldExpand); if (wasExpanded) { stopMonitoringSwipeUpGesture(); animateCollapse(); showManageMenu(false); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__COLLAPSED); } else { animateExpansion(); // TODO: move next line to BubbleData logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__EXPANDED); logBubbleEvent(mExpandedBubble, FrameworkStatsLog.BUBBLE_UICHANGED__ACTION__STACK_EXPANDED); mManager.checkNotificationPanelExpandedState(notifPanelExpanded -> { Loading @@ -2256,6 +2259,14 @@ public class BubbleStackView extends FrameLayout } notifyExpansionChanged(mExpandedBubble, mIsExpanded); announceExpandForAccessibility(mExpandedBubble, mIsExpanded); }; if (mPositioner.isImeVisible()) { hideCurrentInputMethod(onImeHidden); } else { // the IME is already hidden, so run the runnable immediately onImeHidden.run(); } } /** Loading Loading @@ -2373,7 +2384,17 @@ public class BubbleStackView extends FrameLayout * not. */ void hideCurrentInputMethod() { mManager.hideCurrentInputMethod(); mManager.hideCurrentInputMethod(null); } /** * Hides the IME similar to {@link #hideCurrentInputMethod()} but also runs {@code onImeHidden} * after after the IME is hidden. * * @see #hideCurrentInputMethod() */ void hideCurrentInputMethod(Runnable onImeHidden) { mManager.hideCurrentInputMethod(onImeHidden); } /** Set the stack position to whatever the positioner says. */ Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleStackViewManager.kt +3 −3 Original line number Diff line number Diff line Loading @@ -34,7 +34,7 @@ interface BubbleStackViewManager { fun checkNotificationPanelExpandedState(callback: Consumer<Boolean>) /** Requests to hide the current input method. */ fun hideCurrentInputMethod() fun hideCurrentInputMethod(onImeHidden: Runnable?) companion object { Loading @@ -52,8 +52,8 @@ interface BubbleStackViewManager { controller.isNotificationPanelExpanded(callback) } override fun hideCurrentInputMethod() { controller.hideCurrentInputMethod() override fun hideCurrentInputMethod(onImeHidden: Runnable?) { controller.hideCurrentInputMethod(onImeHidden) } } } Loading