Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 159516d4 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Tests for optional bubble overflow" into main

parents b81fa518 9610140b
Loading
Loading
Loading
Loading
+122 −6
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.content.res.Resources
import android.graphics.Color
import android.graphics.drawable.Icon
import android.os.UserHandle
import android.platform.test.flag.junit.SetFlagsRule
import android.view.IWindowManager
import android.view.WindowManager
import android.view.WindowManagerGlobal
@@ -33,6 +34,7 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.internal.protolog.common.ProtoLog
import com.android.launcher3.icons.BubbleIconFactory
import com.android.wm.shell.Flags
import com.android.wm.shell.R
import com.android.wm.shell.bubbles.Bubbles.SysuiProxy
import com.android.wm.shell.bubbles.animation.AnimatableScaleMatrix
@@ -44,19 +46,24 @@ import com.android.wm.shell.taskview.TaskViewTaskController
import com.google.common.truth.Truth.assertThat
import com.google.common.util.concurrent.MoreExecutors.directExecutor
import org.junit.After
import java.util.concurrent.Semaphore
import java.util.concurrent.TimeUnit
import java.util.function.Consumer
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.mock
import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import java.util.concurrent.Semaphore
import java.util.concurrent.TimeUnit
import java.util.function.Consumer

/** Unit tests for [BubbleStackView]. */
@SmallTest
@RunWith(AndroidJUnit4::class)
class BubbleStackViewTest {

    @get:Rule val setFlagsRule = SetFlagsRule()

    private val context = ApplicationProvider.getApplicationContext<Context>()
    private lateinit var positioner: BubblePositioner
    private lateinit var iconFactory: BubbleIconFactory
@@ -66,6 +73,8 @@ class BubbleStackViewTest {
    private lateinit var windowManager: IWindowManager
    private lateinit var bubbleTaskViewFactory: BubbleTaskViewFactory
    private lateinit var bubbleData: BubbleData
    private lateinit var bubbleStackViewManager: FakeBubbleStackViewManager
    private var sysuiProxy = mock<SysuiProxy>()

    @Before
    fun setUp() {
@@ -86,7 +95,6 @@ class BubbleStackViewTest {
                )
            )
        positioner = BubblePositioner(context, windowManager)
        val bubbleStackViewManager = FakeBubbleStackViewManager()
        bubbleData =
            BubbleData(
                context,
@@ -95,8 +103,7 @@ class BubbleStackViewTest {
                BubbleEducationController(context),
                shellExecutor
            )

        val sysuiProxy = mock<SysuiProxy>()
        bubbleStackViewManager = FakeBubbleStackViewManager()
        expandedViewManager = FakeBubbleExpandedViewManager()
        bubbleTaskViewFactory = FakeBubbleTaskViewFactory()
        bubbleStackView =
@@ -234,6 +241,115 @@ class BubbleStackViewTest {
            .inOrder()
    }

    @EnableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    fun testCreateStackView_noOverflowContents_noOverflow() {
        bubbleStackView =
                BubbleStackView(
                        context,
                        bubbleStackViewManager,
                        positioner,
                        bubbleData,
                        null,
                        FloatingContentCoordinator(),
                        { sysuiProxy },
                        shellExecutor
                )

        assertThat(bubbleData.overflowBubbles).isEmpty()
        val bubbleOverflow = bubbleData.overflow
        // Overflow shouldn't be attached
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isEqualTo(-1)
    }

    @EnableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    fun testCreateStackView_hasOverflowContents_hasOverflow() {
        // Add a bubble to the overflow
        val bubble1 = createAndInflateChatBubble(key = "bubble1")
        bubbleData.notificationEntryUpdated(bubble1, false, false)
        bubbleData.dismissBubbleWithKey(bubble1.key, Bubbles.DISMISS_USER_GESTURE)
        assertThat(bubbleData.overflowBubbles).isNotEmpty()

        bubbleStackView =
                BubbleStackView(
                        context,
                        bubbleStackViewManager,
                        positioner,
                        bubbleData,
                        null,
                        FloatingContentCoordinator(),
                        { sysuiProxy },
                        shellExecutor
                )
        val bubbleOverflow = bubbleData.overflow
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isGreaterThan(-1)
    }

    @DisableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    fun testCreateStackView_noOverflowContents_hasOverflow() {
        bubbleStackView =
                BubbleStackView(
                        context,
                        bubbleStackViewManager,
                        positioner,
                        bubbleData,
                        null,
                        FloatingContentCoordinator(),
                        { sysuiProxy },
                        shellExecutor
                )

        assertThat(bubbleData.overflowBubbles).isEmpty()
        val bubbleOverflow = bubbleData.overflow
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isGreaterThan(-1)
    }

    @EnableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    fun showOverflow_true() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            bubbleStackView.showOverflow(true)
        }
        InstrumentationRegistry.getInstrumentation().waitForIdleSync()

        val bubbleOverflow = bubbleData.overflow
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isGreaterThan(-1)
    }

    @EnableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    fun showOverflow_false() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            bubbleStackView.showOverflow(true)
        }
        InstrumentationRegistry.getInstrumentation().waitForIdleSync()
        val bubbleOverflow = bubbleData.overflow
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isGreaterThan(-1)

        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            bubbleStackView.showOverflow(false)
        }
        InstrumentationRegistry.getInstrumentation().waitForIdleSync()

        // The overflow should've been removed
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isEqualTo(-1)
    }

    @DisableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    fun showOverflow_ignored() {
        InstrumentationRegistry.getInstrumentation().runOnMainSync {
            bubbleStackView.showOverflow(false)
        }
        InstrumentationRegistry.getInstrumentation().waitForIdleSync()

        // showOverflow should've been ignored, so the overflow would be attached
        val bubbleOverflow = bubbleData.overflow
        assertThat(bubbleStackView.getBubbleIndex(bubbleOverflow)).isGreaterThan(-1)
    }

    private fun createAndInflateChatBubble(key: String): Bubble {
        val icon = Icon.createWithResource(context.resources, R.drawable.bubble_ic_overflow_button)
        val shortcutInfo = ShortcutInfo.Builder(context, "fakeId").setIcon(icon).build()
+1 −1
Original line number Diff line number Diff line
@@ -3541,7 +3541,7 @@ public class BubbleStackView extends FrameLayout
     */
    int getBubbleIndex(@Nullable BubbleViewProvider provider) {
        if (provider == null) {
            return 0;
            return -1;
        }
        return mBubbleContainer.indexOfChild(provider.getIconView());
    }
+61 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ import com.android.systemui.util.FakeEventLog;
import com.android.systemui.util.settings.FakeGlobalSettings;
import com.android.systemui.util.settings.SystemSettings;
import com.android.systemui.util.time.SystemClock;
import com.android.wm.shell.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.WindowManagerShellWrapper;
import com.android.wm.shell.bubbles.Bubble;
@@ -2300,6 +2301,66 @@ public class BubblesTest extends SysuiTestCase {
        assertThat(bubbleStateListener.mStateChangeCalls).isEqualTo(0);
    }

    @EnableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    public void showBubbleOverflow_hasOverflowContents() {
        mEntryListener.onEntryAdded(mRow);
        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();

        BubbleStackView stackView = mBubbleController.getStackView();
        spyOn(stackView);

        // Dismiss the bubble so it's in the overflow
        mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
        assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();

        verify(stackView).showOverflow(eq(true));
    }

    @EnableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    public void showBubbleOverflow_isEmpty() {
        mEntryListener.onEntryAdded(mRow);
        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();

        BubbleStackView stackView = mBubbleController.getStackView();
        spyOn(stackView);

        // Dismiss the bubble so it's in the overflow
        mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
        assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();
        verify(stackView).showOverflow(eq(true));

        // Cancel the bubble so it's removed from the overflow
        mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();
        verify(stackView).showOverflow(eq(false));
    }

    @DisableFlags(Flags.FLAG_ENABLE_OPTIONAL_BUBBLE_OVERFLOW)
    @Test
    public void showBubbleOverflow_ignored() {
        mEntryListener.onEntryAdded(mRow);
        mEntryListener.onEntryUpdated(mRow, /* fromSystem= */ true);
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();

        BubbleStackView stackView = mBubbleController.getStackView();
        spyOn(stackView);

        // Dismiss the bubble so it's in the overflow
        mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_USER_GESTURE);
        assertThat(mBubbleData.getOverflowBubbles()).isNotEmpty();

        // Cancel the bubble so it's removed from the overflow
        mBubbleController.removeBubble(mRow.getKey(), Bubbles.DISMISS_NOTIF_CANCEL);
        assertThat(mBubbleData.getOverflowBubbles()).isEmpty();

        // Show overflow should never be called if the flag is off
        verify(stackView, never()).showOverflow(anyBoolean());
    }

    /** Creates a bubble using the userId and package. */
    private Bubble createBubble(int userId, String pkg) {
        final UserHandle userHandle = new UserHandle(userId);