Loading libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt +7 −3 Original line number Diff line number Diff line Loading @@ -74,13 +74,17 @@ class NotificationListener : NotificationListenerService() { return wait { instance == null } } fun waitForNotificationToAppear(predicate: (StatusBarNotification) -> Boolean): Boolean { fun waitForNotificationToAppear( predicate: (StatusBarNotification) -> Boolean ): StatusBarNotification? { return instance?.let { wait { it.notifications.values.any(predicate) } waitForResult(extractor = { it.notifications.values.first(predicate) }).second } ?: throw IllegalStateException("NotificationListenerService is not connected") } fun waitForNotificationToDisappear(predicate: (StatusBarNotification) -> Boolean): Boolean { fun waitForNotificationToDisappear( predicate: (StatusBarNotification) -> Boolean ): Boolean { return instance?.let { wait { it.notifications.values.none(predicate) } } ?: throw IllegalStateException("NotificationListenerService is not connected") Loading libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt +5 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,10 @@ abstract class BaseAppHelper( uiDevice.wait(Until.hasObject(appSelector), APP_LAUNCH_WAIT_TIME_MS) } fun waitUntilClosed(): Boolean { return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS) } fun forceStop() = activityManager?.forceStopPackage(packageName) override fun getOpenAppIntent(): Intent { Loading @@ -77,5 +81,6 @@ abstract class BaseAppHelper( companion object { private const val APP_LAUNCH_WAIT_TIME_MS = 10_000L private const val APP_CLOSE_WAIT_TIME_MS = 3_000L } } libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt +1 −2 Original line number Diff line number Diff line Loading @@ -65,8 +65,7 @@ class PipAppHelper( assertNotNull("Pip menu close button is not found", closeButton) closeButton.click() // Give it 1 second, just in case SystemClock.sleep(1_000) waitUntilClosed() } } } libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt +57 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.wm.shell.flicker.pip.tv import android.app.Notification import android.app.PendingIntent import android.os.Bundle import android.service.notification.StatusBarNotification import android.view.Surface import androidx.test.filters.RequiresDevice Loading @@ -25,6 +27,7 @@ import com.android.wm.shell.flicker.NotificationListener.Companion.stopNotificat import com.android.wm.shell.flicker.NotificationListener.Companion.waitForNotificationToAppear import com.android.wm.shell.flicker.NotificationListener.Companion.waitForNotificationToDisappear import org.junit.After import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.FixMethodOrder Loading Loading @@ -64,7 +67,7 @@ class TvPipNotificationTests(rotationName: String, rotation: Int) testApp.launchViaIntent() testApp.clickEnterPipButton() assertTrue("Pip notification should have been posted", assertNotNull("Pip notification should have been posted", waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) }) testApp.closePipWindow() Loading @@ -73,6 +76,43 @@ class TvPipNotificationTests(rotationName: String, rotation: Int) waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) }) } @Test fun pipNotification_closeIntent() { testApp.launchViaIntent() testApp.clickEnterPipButton() val notification: StatusBarNotification = waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) } ?: throw AssertionError("Pip notification should have been posted") notification.deleteIntent?.send() ?: throw AssertionError("Pip notification should contain `delete_intent`") assertTrue("Pip should have closed by sending the `delete_intent`", testApp.waitUntilClosed()) assertTrue("Pip notification should have been dismissed", waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) }) } @Test fun pipNotification_menuIntent() { testApp.launchViaIntent() testApp.clickEnterPipButton() val notification: StatusBarNotification = waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) } ?: throw AssertionError("Pip notification should have been posted") notification.contentIntent?.send() ?: throw AssertionError("Pip notification should contain `content_intent`") assertTrue("Pip menu should have been shown after sending `content_intent`", uiDevice.waitForTvPipMenu()) uiDevice.pressBack() testApp.closePipWindow() } companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic Loading @@ -83,10 +123,23 @@ class TvPipNotificationTests(rotationName: String, rotation: Int) } } private const val PIP_NOTIFICATION_TAG = "PipNotification" private val StatusBarNotification.extras: Bundle? get() = notification?.extras private val StatusBarNotification.title: String get() = notification?.extras?.getString(Notification.EXTRA_TITLE) ?: "" get() = extras?.getString(Notification.EXTRA_TITLE) ?: "" /** Get TV extensions with [android.app.Notification.TvExtender.EXTRA_TV_EXTENDER]. */ private val StatusBarNotification.tvExtensions: Bundle? get() = extras?.getBundle("android.tv.EXTENSIONS") /** "Content" TV intent with key [android.app.Notification.TvExtender.EXTRA_CONTENT_INTENT]. */ private val StatusBarNotification.contentIntent: PendingIntent? get() = tvExtensions?.getParcelable("content_intent") /** "Delete" TV intent with key [android.app.Notification.TvExtender.EXTRA_DELETE_INTENT]. */ private val StatusBarNotification.deleteIntent: PendingIntent? get() = tvExtensions?.getParcelable("delete_intent") private fun StatusBarNotification.isPipNotificationWithTitle(expectedTitle: String): Boolean = tag == PIP_NOTIFICATION_TAG && title == expectedTitle No newline at end of file tag == "PipNotification" && title == expectedTitle No newline at end of file libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt 0 → 100644 +26 −0 Original line number Diff line number Diff line /* * 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 androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice 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 } No newline at end of file Loading
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt +7 −3 Original line number Diff line number Diff line Loading @@ -74,13 +74,17 @@ class NotificationListener : NotificationListenerService() { return wait { instance == null } } fun waitForNotificationToAppear(predicate: (StatusBarNotification) -> Boolean): Boolean { fun waitForNotificationToAppear( predicate: (StatusBarNotification) -> Boolean ): StatusBarNotification? { return instance?.let { wait { it.notifications.values.any(predicate) } waitForResult(extractor = { it.notifications.values.first(predicate) }).second } ?: throw IllegalStateException("NotificationListenerService is not connected") } fun waitForNotificationToDisappear(predicate: (StatusBarNotification) -> Boolean): Boolean { fun waitForNotificationToDisappear( predicate: (StatusBarNotification) -> Boolean ): Boolean { return instance?.let { wait { it.notifications.values.none(predicate) } } ?: throw IllegalStateException("NotificationListenerService is not connected") Loading
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/BaseAppHelper.kt +5 −0 Original line number Diff line number Diff line Loading @@ -66,6 +66,10 @@ abstract class BaseAppHelper( uiDevice.wait(Until.hasObject(appSelector), APP_LAUNCH_WAIT_TIME_MS) } fun waitUntilClosed(): Boolean { return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS) } fun forceStop() = activityManager?.forceStopPackage(packageName) override fun getOpenAppIntent(): Intent { Loading @@ -77,5 +81,6 @@ abstract class BaseAppHelper( companion object { private const val APP_LAUNCH_WAIT_TIME_MS = 10_000L private const val APP_CLOSE_WAIT_TIME_MS = 3_000L } }
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/PipAppHelper.kt +1 −2 Original line number Diff line number Diff line Loading @@ -65,8 +65,7 @@ class PipAppHelper( assertNotNull("Pip menu close button is not found", closeButton) closeButton.click() // Give it 1 second, just in case SystemClock.sleep(1_000) waitUntilClosed() } } }
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt +57 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,8 @@ package com.android.wm.shell.flicker.pip.tv import android.app.Notification import android.app.PendingIntent import android.os.Bundle import android.service.notification.StatusBarNotification import android.view.Surface import androidx.test.filters.RequiresDevice Loading @@ -25,6 +27,7 @@ import com.android.wm.shell.flicker.NotificationListener.Companion.stopNotificat import com.android.wm.shell.flicker.NotificationListener.Companion.waitForNotificationToAppear import com.android.wm.shell.flicker.NotificationListener.Companion.waitForNotificationToDisappear import org.junit.After import org.junit.Assert.assertNotNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.FixMethodOrder Loading Loading @@ -64,7 +67,7 @@ class TvPipNotificationTests(rotationName: String, rotation: Int) testApp.launchViaIntent() testApp.clickEnterPipButton() assertTrue("Pip notification should have been posted", assertNotNull("Pip notification should have been posted", waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) }) testApp.closePipWindow() Loading @@ -73,6 +76,43 @@ class TvPipNotificationTests(rotationName: String, rotation: Int) waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) }) } @Test fun pipNotification_closeIntent() { testApp.launchViaIntent() testApp.clickEnterPipButton() val notification: StatusBarNotification = waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) } ?: throw AssertionError("Pip notification should have been posted") notification.deleteIntent?.send() ?: throw AssertionError("Pip notification should contain `delete_intent`") assertTrue("Pip should have closed by sending the `delete_intent`", testApp.waitUntilClosed()) assertTrue("Pip notification should have been dismissed", waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) }) } @Test fun pipNotification_menuIntent() { testApp.launchViaIntent() testApp.clickEnterPipButton() val notification: StatusBarNotification = waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) } ?: throw AssertionError("Pip notification should have been posted") notification.contentIntent?.send() ?: throw AssertionError("Pip notification should contain `content_intent`") assertTrue("Pip menu should have been shown after sending `content_intent`", uiDevice.waitForTvPipMenu()) uiDevice.pressBack() testApp.closePipWindow() } companion object { @Parameterized.Parameters(name = "{0}") @JvmStatic Loading @@ -83,10 +123,23 @@ class TvPipNotificationTests(rotationName: String, rotation: Int) } } private const val PIP_NOTIFICATION_TAG = "PipNotification" private val StatusBarNotification.extras: Bundle? get() = notification?.extras private val StatusBarNotification.title: String get() = notification?.extras?.getString(Notification.EXTRA_TITLE) ?: "" get() = extras?.getString(Notification.EXTRA_TITLE) ?: "" /** Get TV extensions with [android.app.Notification.TvExtender.EXTRA_TV_EXTENDER]. */ private val StatusBarNotification.tvExtensions: Bundle? get() = extras?.getBundle("android.tv.EXTENSIONS") /** "Content" TV intent with key [android.app.Notification.TvExtender.EXTRA_CONTENT_INTENT]. */ private val StatusBarNotification.contentIntent: PendingIntent? get() = tvExtensions?.getParcelable("content_intent") /** "Delete" TV intent with key [android.app.Notification.TvExtender.EXTRA_DELETE_INTENT]. */ private val StatusBarNotification.deleteIntent: PendingIntent? get() = tvExtensions?.getParcelable("delete_intent") private fun StatusBarNotification.isPipNotificationWithTitle(expectedTitle: String): Boolean = tag == PIP_NOTIFICATION_TAG && title == expectedTitle No newline at end of file tag == "PipNotification" && title == expectedTitle No newline at end of file
libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvUtils.kt 0 → 100644 +26 −0 Original line number Diff line number Diff line /* * 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 androidx.test.uiautomator.By import androidx.test.uiautomator.UiDevice 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 } No newline at end of file