Initial screenshot tests for bubble bar view
Flag: com.android.wm.shell.enable_bubble_bar
Bug: 355454021
Test: atest BubbleBarViewScreenshotTests
Change-Id: Id74c78d99a8b4528bb473c5a751edb19bda34007
diff --git a/quickstep/Android.bp b/quickstep/Android.bp
index 4c724dc..2ef9f82 100644
--- a/quickstep/Android.bp
+++ b/quickstep/Android.bp
@@ -64,3 +64,11 @@
"tests/multivalentScreenshotTests/src/**/*.kt",
],
}
+
+filegroup {
+ name: "launcher3-quickstep-testing",
+ path: "testing",
+ srcs: [
+ "testing/**/*.kt",
+ ],
+}
diff --git a/quickstep/testing/com/android/launcher3/taskbar/bubbles/testing/FakeBubbleViewFactory.kt b/quickstep/testing/com/android/launcher3/taskbar/bubbles/testing/FakeBubbleViewFactory.kt
new file mode 100644
index 0000000..37a07c3
--- /dev/null
+++ b/quickstep/testing/com/android/launcher3/taskbar/bubbles/testing/FakeBubbleViewFactory.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles.testing
+
+import android.app.Notification
+import android.content.Context
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Paint
+import android.util.PathParser
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import com.android.launcher3.R
+import com.android.launcher3.taskbar.bubbles.BubbleBarBubble
+import com.android.launcher3.taskbar.bubbles.BubbleView
+import com.android.wm.shell.shared.bubbles.BubbleInfo
+
+object FakeBubbleViewFactory {
+
+ /** Inflates a [BubbleView] and adds it to the [parent] view if it is present. */
+ fun createBubble(
+ context: Context,
+ key: String,
+ parent: ViewGroup?,
+ iconSize: Int = 50,
+ iconColor: Int,
+ badgeColor: Int = Color.RED,
+ dotColor: Int = Color.BLUE,
+ suppressNotification: Boolean = false,
+ ): BubbleView {
+ val inflater = LayoutInflater.from(context)
+ // BubbleView uses launcher's badge to icon ratio and expects the badge image to already
+ // have the right size
+ val badgeToIconRatio = 0.444f
+ val badgeRadius = iconSize * badgeToIconRatio / 2
+ val icon = createCircleBitmap(radius = iconSize / 2, color = iconColor)
+ val badge = createCircleBitmap(radius = badgeRadius.toInt(), color = badgeColor)
+
+ val flags =
+ if (suppressNotification) Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION else 0
+ val bubbleInfo =
+ BubbleInfo(key, flags, null, null, 0, context.packageName, null, null, false, true)
+ val bubbleView = inflater.inflate(R.layout.bubblebar_item_view, parent, false) as BubbleView
+ val dotPath =
+ PathParser.createPathFromPathData(
+ context.resources.getString(com.android.internal.R.string.config_icon_mask)
+ )
+ val bubble =
+ BubbleBarBubble(bubbleInfo, bubbleView, badge, icon, dotColor, dotPath, "test app")
+ bubbleView.setBubble(bubble)
+ return bubbleView
+ }
+
+ private fun createCircleBitmap(radius: Int, color: Int): Bitmap {
+ val bitmap = Bitmap.createBitmap(radius * 2, radius * 2, Bitmap.Config.ARGB_8888)
+ val canvas = Canvas(bitmap)
+ canvas.drawARGB(0, 0, 0, 0)
+ val paint = Paint()
+ paint.color = color
+ canvas.drawCircle(radius.toFloat(), radius.toFloat(), radius.toFloat(), paint)
+ return bitmap
+ }
+}
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt
new file mode 100644
index 0000000..e4b8069
--- /dev/null
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewScreenshotTest.kt
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.taskbar.bubbles
+
+import android.content.Context
+import android.graphics.Color
+import android.platform.test.rule.ScreenRecordRule
+import android.view.View
+import android.widget.FrameLayout
+import android.widget.FrameLayout.LayoutParams.MATCH_PARENT
+import android.widget.FrameLayout.LayoutParams.WRAP_CONTENT
+import androidx.activity.ComponentActivity
+import androidx.test.core.app.ApplicationProvider
+import com.android.launcher3.R
+import com.android.launcher3.taskbar.bubbles.testing.FakeBubbleViewFactory
+import com.google.android.apps.nexuslauncher.imagecomparison.goldenpathmanager.ViewScreenshotGoldenPathManager
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4
+import platform.test.runner.parameterized.Parameters
+import platform.test.screenshot.DeviceEmulationSpec
+import platform.test.screenshot.Displays
+import platform.test.screenshot.ViewScreenshotTestRule
+import platform.test.screenshot.getEmulatedDevicePathConfig
+
+/** Screenshot tests for [BubbleBarView]. */
+@RunWith(ParameterizedAndroidJunit4::class)
+@ScreenRecordRule.ScreenRecord
+class BubbleBarViewScreenshotTest(emulationSpec: DeviceEmulationSpec) {
+
+ private val context = ApplicationProvider.getApplicationContext<Context>()
+ private lateinit var bubbleBarView: BubbleBarView
+
+ companion object {
+ @Parameters(name = "{0}")
+ @JvmStatic
+ fun getTestSpecs() =
+ DeviceEmulationSpec.forDisplays(
+ Displays.Phone,
+ isDarkTheme = false,
+ isLandscape = false,
+ )
+ }
+
+ @get:Rule
+ val screenshotRule =
+ ViewScreenshotTestRule(
+ emulationSpec,
+ ViewScreenshotGoldenPathManager(getEmulatedDevicePathConfig(emulationSpec)),
+ )
+
+ @Test
+ fun bubbleBarView_collapsed_oneBubble() {
+ screenshotRule.screenshotTest("bubbleBarView_collapsed_oneBubble") { activity ->
+ activity.actionBar?.hide()
+ setupBubbleBarView()
+ bubbleBarView.addBubble(createBubble("key1", Color.GREEN))
+ val container = FrameLayout(context)
+ val lp = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ container.layoutParams = lp
+ container.addView(bubbleBarView)
+ container
+ }
+ }
+
+ @Test
+ fun bubbleBarView_collapsed_twoBubbles() {
+ screenshotRule.screenshotTest("bubbleBarView_collapsed_twoBubbles") { activity ->
+ activity.actionBar?.hide()
+ setupBubbleBarView()
+ bubbleBarView.addBubble(createBubble("key1", Color.GREEN))
+ bubbleBarView.addBubble(createBubble("key2", Color.CYAN))
+ val container = FrameLayout(context)
+ val lp = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ container.layoutParams = lp
+ container.addView(bubbleBarView)
+ container
+ }
+ }
+
+ @Test
+ fun bubbleBarView_expanded_threeBubbles() {
+ // if we're still expanding, wait with taking a screenshot
+ val shouldWait: (ComponentActivity, View) -> Boolean = { _, _ -> bubbleBarView.isExpanding }
+ screenshotRule.screenshotTest(
+ "bubbleBarView_expanded_threeBubbles",
+ checkView = shouldWait,
+ ) { activity ->
+ activity.actionBar?.hide()
+ setupBubbleBarView()
+ bubbleBarView.addBubble(createBubble("key1", Color.GREEN))
+ bubbleBarView.addBubble(createBubble("key2", Color.CYAN))
+ bubbleBarView.addBubble(createBubble("key3", Color.MAGENTA))
+ val container = FrameLayout(context)
+ val lp = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
+ container.layoutParams = lp
+ container.addView(bubbleBarView)
+ bubbleBarView.isExpanded = true
+ container
+ }
+ }
+
+ private fun setupBubbleBarView() {
+ bubbleBarView = BubbleBarView(context)
+ val lp = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
+ bubbleBarView.layoutParams = lp
+ val paddingTop =
+ context.resources.getDimensionPixelSize(R.dimen.bubblebar_pointer_visible_size)
+ bubbleBarView.setPadding(0, paddingTop, 0, 0)
+ bubbleBarView.visibility = View.VISIBLE
+ bubbleBarView.alpha = 1f
+ }
+
+ private fun createBubble(key: String, color: Int): BubbleView {
+ val bubbleView =
+ FakeBubbleViewFactory.createBubble(
+ context,
+ key,
+ parent = bubbleBarView,
+ iconColor = color,
+ )
+ bubbleView.showDotIfNeeded(1f)
+ bubbleBarView.setSelectedBubble(bubbleView)
+ return bubbleView
+ }
+}
diff --git a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt
index eb459ff..47f393f 100644
--- a/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt
+++ b/quickstep/tests/multivalentScreenshotTests/src/com/android/launcher3/taskbar/bubbles/BubbleViewScreenshotTest.kt
@@ -15,17 +15,10 @@
*/
package com.android.launcher3.taskbar.bubbles
-import android.app.Notification
import android.content.Context
-import android.graphics.Bitmap
-import android.graphics.Canvas
import android.graphics.Color
-import android.graphics.Paint
-import android.util.PathParser
-import android.view.LayoutInflater
import androidx.test.core.app.ApplicationProvider
-import com.android.launcher3.R
-import com.android.wm.shell.shared.bubbles.BubbleInfo
+import com.android.launcher3.taskbar.bubbles.testing.FakeBubbleViewFactory
import com.google.android.apps.nexuslauncher.imagecomparison.goldenpathmanager.ViewScreenshotGoldenPathManager
import org.junit.Rule
import org.junit.Test
@@ -50,7 +43,7 @@
DeviceEmulationSpec.forDisplays(
Displays.Phone,
isDarkTheme = false,
- isLandscape = false
+ isLandscape = false,
)
}
@@ -58,7 +51,7 @@
val screenshotRule =
ViewScreenshotTestRule(
emulationSpec,
- ViewScreenshotGoldenPathManager(getEmulatedDevicePathConfig(emulationSpec))
+ ViewScreenshotGoldenPathManager(getEmulatedDevicePathConfig(emulationSpec)),
)
@Test
@@ -86,39 +79,16 @@
}
private fun setupBubbleView(suppressNotification: Boolean = false): BubbleView {
- val inflater = LayoutInflater.from(context)
-
- val iconSize = 100
- // BubbleView uses launcher's badge to icon ratio and expects the badge image to already
- // have the right size
- val badgeToIconRatio = 0.444f
- val badgeRadius = iconSize * badgeToIconRatio / 2
- val icon = createCircleBitmap(radius = iconSize / 2, color = Color.LTGRAY)
- val badge = createCircleBitmap(radius = badgeRadius.toInt(), color = Color.RED)
-
- val flags =
- if (suppressNotification) Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION else 0
- val bubbleInfo =
- BubbleInfo("key", flags, null, null, 0, context.packageName, null, null, false, true)
- val bubbleView = inflater.inflate(R.layout.bubblebar_item_view, null) as BubbleView
- val dotPath =
- PathParser.createPathFromPathData(
- context.resources.getString(com.android.internal.R.string.config_icon_mask)
+ val bubbleView =
+ FakeBubbleViewFactory.createBubble(
+ context,
+ key = "key",
+ parent = null,
+ iconSize = 100,
+ iconColor = Color.LTGRAY,
+ suppressNotification = suppressNotification,
)
- val bubble =
- BubbleBarBubble(bubbleInfo, bubbleView, badge, icon, Color.BLUE, dotPath, "test app")
- bubbleView.setBubble(bubble)
bubbleView.showDotIfNeeded(1f)
return bubbleView
}
-
- private fun createCircleBitmap(radius: Int, color: Int): Bitmap {
- val bitmap = Bitmap.createBitmap(radius * 2, radius * 2, Bitmap.Config.ARGB_8888)
- val canvas = Canvas(bitmap)
- canvas.drawARGB(0, 0, 0, 0)
- val paint = Paint()
- paint.color = color
- canvas.drawCircle(radius.toFloat(), radius.toFloat(), radius.toFloat(), paint)
- return bitmap
- }
}