Merge "Add TvPipMenuTests"
diff --git a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
index d8474b8..0d684e8 100644
--- a/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
+++ b/libs/WindowManager/Shell/res/layout/tv_pip_menu.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/tv_pip_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
index 55796da..4ab5c6a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt
@@ -26,6 +26,7 @@
import android.support.test.launcherhelper.LauncherStrategyFactory
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.server.wm.flicker.helpers.StandardAppHelper
import com.android.wm.shell.flicker.TEST_APP_PACKAGE_NAME
@@ -60,6 +61,9 @@
getApplicationLabel(getApplicationInfo(packageName, 0)).toString()
}
+ val ui: UiObject2?
+ get() = uiDevice.findObject(appSelector)
+
fun launchViaIntent() {
context.startActivity(openAppIntent)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
new file mode 100644
index 0000000..33b6902
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipMenuTests.kt
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2020 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.wm.shell.flicker.pip.tv
+
+import android.os.SystemClock
+import androidx.test.filters.RequiresDevice
+import org.junit.Assert.assertNotNull
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.Parameterized
+
+/**
+ * Test Pip Menu on TV.
+ * To run this test: `atest WMShellFlickerTests:TvPipMenuTests`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+class TvPipMenuTests(rotationName: String, rotation: Int)
+ : TvPipTestBase(rotationName, rotation) {
+
+ @Before
+ override fun setUp() {
+ super.setUp()
+ // Launch the app and go to PiP
+ testApp.launchViaIntent()
+ testApp.clickEnterPipButton()
+ }
+
+ @Test
+ fun pipMenu_open() {
+ // Pressing the Window key should bring up Pip menu
+ uiDevice.pressWindowKey()
+ val pipMenu = uiDevice.waitForTvPipMenu()
+ ?: fail("Pip notification should have been dismissed")
+
+ assertTrue("Pip menu should be shown fullscreen", pipMenu.isFullscreen(uiDevice))
+
+ testApp.closePipWindow()
+ }
+
+ @Test
+ fun pipMenu_backButton() {
+ // Pressing the Window key should bring up Pip menu
+ uiDevice.pressWindowKey()
+ assertNotNull("Pip notification should have been dismissed", uiDevice.waitForTvPipMenu())
+
+ // Pressing the Back key should close the Pip menu
+ uiDevice.pressBack()
+ assertTrue("Pip notification should have closed", uiDevice.waitForTvPipMenuToClose())
+
+ testApp.closePipWindow()
+ }
+
+ @Test
+ fun pipMenu_closeButton() {
+ // Pressing the Window key should bring up Pip menu
+ uiDevice.pressWindowKey()
+ assertNotNull("Pip notification should have been dismissed", uiDevice.waitForTvPipMenu())
+
+ // PiP menu should contain the Close button
+ val closeButton = uiDevice.findTvPipMenuCloseButton()
+ ?: fail("\"Close PIP\" button should be shown in Pip menu")
+
+ // Clicking on the Close button should close the app
+ closeButton.click()
+ assertTrue("\"Close PIP\" button should close the PiP", testApp.waitUntilClosed())
+ }
+
+ @Test
+ fun pipMenu_fullscreenButton() {
+ // Pressing the Window key should bring up Pip menu
+ uiDevice.pressWindowKey()
+ assertNotNull("Pip notification should have been dismissed", uiDevice.waitForTvPipMenu())
+
+ // PiP menu should contain the Fullscreen button
+ val fullscreenButton = uiDevice.findTvPipMenuFullscreenButton()
+ ?: fail("\"Full screen\" button should be shown in Pip menu")
+
+ // Clicking on the fullscreen button should return app to the fullscreen mode.
+ // Click, wait for 3 seconds, check the app is fullscreen
+ fullscreenButton.click()
+ SystemClock.sleep(3_000L)
+ assertTrue("\"Full screen\" button should open the app fullscreen",
+ testApp.ui?.isFullscreen(uiDevice) ?: false)
+
+ // Close the app
+ uiDevice.pressBack()
+ testApp.waitUntilClosed()
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> = rotationParams
+ }
+}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
index 1d44658..7a9b33b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
@@ -20,7 +20,6 @@
import android.app.PendingIntent
import android.os.Bundle
import android.service.notification.StatusBarNotification
-import android.view.Surface
import androidx.test.filters.RequiresDevice
import com.android.wm.shell.flicker.NotificationListener.Companion.findNotification
import com.android.wm.shell.flicker.NotificationListener.Companion.startNotificationListener
@@ -32,10 +31,8 @@
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Before
-import org.junit.FixMethodOrder
import org.junit.Test
import org.junit.runner.RunWith
-import org.junit.runners.MethodSorters
import org.junit.runners.Parameterized
/**
@@ -44,7 +41,6 @@
*/
@RequiresDevice
@RunWith(Parameterized::class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
class TvPipNotificationTests(rotationName: String, rotation: Int)
: TvPipTestBase(rotationName, rotation) {
@@ -60,7 +56,6 @@
@After
override fun tearDown() {
stopNotificationListener()
- testApp.forceStop()
super.tearDown()
}
@@ -108,7 +103,7 @@
notification.contentIntent?.send()
?: fail("Pip notification should contain `content_intent`")
- assertTrue("Pip menu should have been shown after sending `content_intent`",
+ assertNotNull("Pip menu should have been shown after sending `content_intent`",
uiDevice.waitForTvPipMenu())
uiDevice.pressBack()
@@ -156,18 +151,13 @@
testApp.closePipWindow()
}
- private fun fail(message: String): Nothing = throw AssertionError(message)
-
companion object {
private const val TITLE_MEDIA_SESSION_PLAYING = "TestApp media is playing"
private const val TITLE_MEDIA_SESSION_PAUSED = "TestApp media is paused"
@Parameterized.Parameters(name = "{0}")
@JvmStatic
- fun getParams(): Collection<Array<Any>> {
- val supportedRotations = intArrayOf(Surface.ROTATION_0)
- return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
- }
+ fun getParams(): Collection<Array<Any>> = rotationParams
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
index 104248c..05f4b0b 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -18,6 +18,8 @@
import android.content.pm.PackageManager.FEATURE_LEANBACK
import android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY
+import android.view.Surface.ROTATION_0
+import android.view.Surface.rotationToString
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.wm.shell.flicker.pip.PipTestBase
import org.junit.After
@@ -40,5 +42,14 @@
@After
open fun tearDown() {
+ testApp.forceStop()
+ }
+
+ protected fun fail(message: String): Nothing = throw AssertionError(message)
+
+ companion object {
+ @JvmStatic
+ protected val rotationParams: Collection<Array<Any>> =
+ listOf(arrayOf(rotationToString(ROTATION_0), ROTATION_0))
}
}
\ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
index ac9ab13..d9e6ff3 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt
@@ -16,11 +16,35 @@
package com.android.wm.shell.flicker.pip.tv
+import android.view.KeyEvent
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
+import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
import com.android.wm.shell.flicker.SYSTEM_UI_PACKAGE_NAME
-fun UiDevice.waitForTvPipMenu(): Boolean {
- return wait(Until.findObject(By.res(SYSTEM_UI_PACKAGE_NAME, "pip_controls")), 3_000) != null
+/** Id of the root view in the com.android.wm.shell.pip.tv.PipMenuActivity */
+private const val TV_PIP_MENU_ROOT_ID = "tv_pip_menu"
+private const val TV_PIP_MENU_CLOSE_BUTTON_ID = "close_button"
+private const val TV_PIP_MENU_FULLSCREEN_BUTTON_ID = "full_button"
+
+private const val WAIT_TIME_MS = 3_000L
+
+private val tvPipMenuSelector = By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_ROOT_ID)
+
+fun UiDevice.pressWindowKey() = pressKeyCode(KeyEvent.KEYCODE_WINDOW)
+
+fun UiDevice.waitForTvPipMenu(): UiObject2? =
+ wait(Until.findObject(tvPipMenuSelector), WAIT_TIME_MS)
+
+fun UiDevice.waitForTvPipMenuToClose(): Boolean = wait(Until.gone(tvPipMenuSelector), WAIT_TIME_MS)
+
+fun UiDevice.findTvPipMenuCloseButton(): UiObject2? = findObject(
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_CLOSE_BUTTON_ID))
+
+fun UiDevice.findTvPipMenuFullscreenButton(): UiObject2? = findObject(
+ By.res(SYSTEM_UI_PACKAGE_NAME, TV_PIP_MENU_FULLSCREEN_BUTTON_ID))
+
+fun UiObject2.isFullscreen(uiDevice: UiDevice): Boolean = visibleBounds.run {
+ height() == uiDevice.displayHeight && width() == uiDevice.displayWidth
}
\ No newline at end of file