Loading libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerTest.kt +99 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.graphics.drawable.Icon import android.os.Handler import android.os.UserHandle import android.os.UserManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import android.platform.test.flag.junit.SetFlagsRule Loading @@ -37,6 +38,7 @@ import android.view.IWindowManager import android.view.InsetsSource import android.view.InsetsState import android.view.SurfaceControl import android.view.View import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.TRANSIT_CHANGE Loading @@ -55,6 +57,7 @@ import com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE import com.android.wm.shell.R import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener import com.android.wm.shell.bubbles.Bubbles.DISMISS_USER_GESTURE import com.android.wm.shell.bubbles.Bubbles.SysuiProxy import com.android.wm.shell.bubbles.storage.BubblePersistentRepository import com.android.wm.shell.common.DisplayController Loading Loading @@ -710,6 +713,102 @@ class BubbleControllerTest(flags: FlagsParameterization) { assertThat(bubble.taskView.alpha).isEqualTo(0) } @DisableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOut_hasBubbles() { val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } assertThat(bubbleData.hasBubbles()).isTrue() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.stackView!!.visibility).isEqualTo(View.VISIBLE) } @DisableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOut_noBubbles() { val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } getInstrumentation().runOnMainSync { bubbleController.dismissBubble("key", DISMISS_USER_GESTURE) } assertThat(bubbleData.hasBubbles()).isFalse() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.stackView!!.visibility).isEqualTo(View.INVISIBLE) } @EnableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOutBubbleBar_hasBubbles() { bubblePositioner.update(deviceConfigUnfolded) bubblePositioner.isShowingInBubbleBar = true getInstrumentation().runOnMainSync { bubbleController.setLauncherHasBubbleBar(true) bubbleController.registerBubbleStateListener(FakeBubblesStateListener()) } val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } assertThat(bubbleData.hasBubbles()).isTrue() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.layerView!!.visibility).isEqualTo(View.VISIBLE) } @EnableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOutBubbleBar_noBubbles() { bubblePositioner.update(deviceConfigUnfolded) bubblePositioner.isShowingInBubbleBar = true getInstrumentation().runOnMainSync { bubbleController.setLauncherHasBubbleBar(true) bubbleController.registerBubbleStateListener(FakeBubblesStateListener()) } val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } getInstrumentation().runOnMainSync { bubbleController.dismissBubble("key", DISMISS_USER_GESTURE) } assertThat(bubbleData.hasBubbles()).isFalse() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.layerView!!.visibility).isEqualTo(View.INVISIBLE) } private fun createBubble(key: String, taskId: Int = 0): Bubble { val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button) val shortcutInfo = ShortcutInfo.Builder(context, "fakeId").setIcon(icon).build() Loading libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +24 −20 Original line number Diff line number Diff line Loading @@ -204,6 +204,8 @@ public class BubbleController implements ConfigurationChangeListener, void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer); /** Called when the bubble overflow empty state changes, used to show/hide the overflow. */ void bubbleOverflowChanged(boolean hasBubbles); /** Called when the visibility of bubble views should be updated. */ void updateVisibility(boolean visible); } private final Context mContext; Loading Loading @@ -1295,17 +1297,15 @@ public class BubbleController implements ConfigurationChangeListener, }; /** * Called by the BubbleStackView and whenever all bubbles have animated out, and none have been * added in the meantime. * Called by the view displaying bubbles once all bubbles have finished animating out. */ public void onAllBubblesAnimatedOut() { if (mStackView != null) { mStackView.setVisibility(INVISIBLE); removeFromWindowManagerMaybe(); } else if (mLayerView != null) { mLayerView.setVisibility(INVISIBLE); removeFromWindowManagerMaybe(); if (hasBubbles()) { // Bubbles could've been added in the time it takes to animate out the bubbles. return; } mBubbleViewCallback.updateVisibility(false /* visible */); removeFromWindowManagerMaybe(); } /** Loading Loading @@ -2492,6 +2492,13 @@ public class BubbleController implements ConfigurationChangeListener, } } } @Override public void updateVisibility(boolean visible) { if (mStackView != null) { mStackView.setVisibility(visible ? VISIBLE : INVISIBLE); } } }; /** When bubbles are in the bubble bar, this will be used to notify bubble bar views. */ Loading Loading @@ -2571,6 +2578,13 @@ public class BubbleController implements ConfigurationChangeListener, } } } @Override public void updateVisibility(boolean visible) { if (mLayerView != null) { mLayerView.setVisibility(visible ? VISIBLE : INVISIBLE); } } }; @SuppressWarnings("FieldCanBeLocal") Loading Loading @@ -2832,22 +2846,12 @@ public class BubbleController implements ConfigurationChangeListener, mIsStatusBarShade, hasBubbles()); if (!mIsStatusBarShade) { // Bubbles don't appear when the device is locked. if (mStackView != null) { mStackView.setVisibility(INVISIBLE); } if (mLayerView != null) { mLayerView.setVisibility(INVISIBLE); } mBubbleViewCallback.updateVisibility(false /* visible */); } else if (hasBubbles()) { // If we're unlocked, show the stack if we have bubbles. If we don't have bubbles, the // stack will be set to INVISIBLE in onAllBubblesAnimatedOut after the bubbles animate // out. if (mStackView != null) { mStackView.setVisibility(VISIBLE); } if (mLayerView != null) { mLayerView.setVisibility(VISIBLE); } mBubbleViewCallback.updateVisibility(true /* visible */); } if (mStackView != null) { Loading Loading
libs/WindowManager/Shell/multivalentTests/src/com/android/wm/shell/bubbles/BubbleControllerTest.kt +99 −0 Original line number Diff line number Diff line Loading @@ -30,6 +30,7 @@ import android.graphics.drawable.Icon import android.os.Handler import android.os.UserHandle import android.os.UserManager import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import android.platform.test.flag.junit.SetFlagsRule Loading @@ -37,6 +38,7 @@ import android.view.IWindowManager import android.view.InsetsSource import android.view.InsetsState import android.view.SurfaceControl import android.view.View import android.view.WindowInsets import android.view.WindowManager import android.view.WindowManager.TRANSIT_CHANGE Loading @@ -55,6 +57,7 @@ import com.android.wm.shell.Flags.FLAG_ENABLE_CREATE_ANY_BUBBLE import com.android.wm.shell.R import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.bubbles.Bubbles.BubbleExpandListener import com.android.wm.shell.bubbles.Bubbles.DISMISS_USER_GESTURE import com.android.wm.shell.bubbles.Bubbles.SysuiProxy import com.android.wm.shell.bubbles.storage.BubblePersistentRepository import com.android.wm.shell.common.DisplayController Loading Loading @@ -710,6 +713,102 @@ class BubbleControllerTest(flags: FlagsParameterization) { assertThat(bubble.taskView.alpha).isEqualTo(0) } @DisableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOut_hasBubbles() { val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } assertThat(bubbleData.hasBubbles()).isTrue() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.stackView!!.visibility).isEqualTo(View.VISIBLE) } @DisableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOut_noBubbles() { val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } getInstrumentation().runOnMainSync { bubbleController.dismissBubble("key", DISMISS_USER_GESTURE) } assertThat(bubbleData.hasBubbles()).isFalse() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.stackView!!.visibility).isEqualTo(View.INVISIBLE) } @EnableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOutBubbleBar_hasBubbles() { bubblePositioner.update(deviceConfigUnfolded) bubblePositioner.isShowingInBubbleBar = true getInstrumentation().runOnMainSync { bubbleController.setLauncherHasBubbleBar(true) bubbleController.registerBubbleStateListener(FakeBubblesStateListener()) } val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } assertThat(bubbleData.hasBubbles()).isTrue() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.layerView!!.visibility).isEqualTo(View.VISIBLE) } @EnableFlags(FLAG_ENABLE_BUBBLE_BAR) @Test fun onAllBubblesAnimatedOutBubbleBar_noBubbles() { bubblePositioner.update(deviceConfigUnfolded) bubblePositioner.isShowingInBubbleBar = true getInstrumentation().runOnMainSync { bubbleController.setLauncherHasBubbleBar(true) bubbleController.registerBubbleStateListener(FakeBubblesStateListener()) } val bubble = createBubble("key") getInstrumentation().runOnMainSync { bubbleController.inflateAndAdd( bubble, /* suppressFlyout= */ true, /* showInShade= */ true ) } getInstrumentation().runOnMainSync { bubbleController.dismissBubble("key", DISMISS_USER_GESTURE) } assertThat(bubbleData.hasBubbles()).isFalse() getInstrumentation().runOnMainSync { bubbleController.onAllBubblesAnimatedOut() } assertThat(bubbleController.layerView!!.visibility).isEqualTo(View.INVISIBLE) } private fun createBubble(key: String, taskId: Int = 0): Bubble { val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button) val shortcutInfo = ShortcutInfo.Builder(context, "fakeId").setIcon(icon).build() Loading
libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubbleController.java +24 −20 Original line number Diff line number Diff line Loading @@ -204,6 +204,8 @@ public class BubbleController implements ConfigurationChangeListener, void bubbleOrderChanged(List<Bubble> bubbleOrder, boolean updatePointer); /** Called when the bubble overflow empty state changes, used to show/hide the overflow. */ void bubbleOverflowChanged(boolean hasBubbles); /** Called when the visibility of bubble views should be updated. */ void updateVisibility(boolean visible); } private final Context mContext; Loading Loading @@ -1295,17 +1297,15 @@ public class BubbleController implements ConfigurationChangeListener, }; /** * Called by the BubbleStackView and whenever all bubbles have animated out, and none have been * added in the meantime. * Called by the view displaying bubbles once all bubbles have finished animating out. */ public void onAllBubblesAnimatedOut() { if (mStackView != null) { mStackView.setVisibility(INVISIBLE); removeFromWindowManagerMaybe(); } else if (mLayerView != null) { mLayerView.setVisibility(INVISIBLE); removeFromWindowManagerMaybe(); if (hasBubbles()) { // Bubbles could've been added in the time it takes to animate out the bubbles. return; } mBubbleViewCallback.updateVisibility(false /* visible */); removeFromWindowManagerMaybe(); } /** Loading Loading @@ -2492,6 +2492,13 @@ public class BubbleController implements ConfigurationChangeListener, } } } @Override public void updateVisibility(boolean visible) { if (mStackView != null) { mStackView.setVisibility(visible ? VISIBLE : INVISIBLE); } } }; /** When bubbles are in the bubble bar, this will be used to notify bubble bar views. */ Loading Loading @@ -2571,6 +2578,13 @@ public class BubbleController implements ConfigurationChangeListener, } } } @Override public void updateVisibility(boolean visible) { if (mLayerView != null) { mLayerView.setVisibility(visible ? VISIBLE : INVISIBLE); } } }; @SuppressWarnings("FieldCanBeLocal") Loading Loading @@ -2832,22 +2846,12 @@ public class BubbleController implements ConfigurationChangeListener, mIsStatusBarShade, hasBubbles()); if (!mIsStatusBarShade) { // Bubbles don't appear when the device is locked. if (mStackView != null) { mStackView.setVisibility(INVISIBLE); } if (mLayerView != null) { mLayerView.setVisibility(INVISIBLE); } mBubbleViewCallback.updateVisibility(false /* visible */); } else if (hasBubbles()) { // If we're unlocked, show the stack if we have bubbles. If we don't have bubbles, the // stack will be set to INVISIBLE in onAllBubblesAnimatedOut after the bubbles animate // out. if (mStackView != null) { mStackView.setVisibility(VISIBLE); } if (mLayerView != null) { mLayerView.setVisibility(VISIBLE); } mBubbleViewCallback.updateVisibility(true /* visible */); } if (mStackView != null) { Loading