summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sergey Nikolaienkov <sergeynv@google.com> 2020-11-02 08:42:50 +0000
committer Sergey Nikolaienkov <sergeynv@google.com> 2020-11-04 12:32:51 +0000
commit757e60e05726d28a7c8b5f79930d501cee74af7c (patch)
tree1afc263a1dbb64a4ef90142760d86bbc3d50612e
parent58dc55b6e84f32124a907fd9f44e55ee7a5fbeae (diff)
Introduce .wm.flicker.pip.tv.TvPipNotificationTests
Move first test out of android.systemui.cts.tv.PipNotificationTests to com.android.wm.shell.flicker.pip.tv.TvPipNotification tests. Bug: 171520419 Test: atest WMShellFlickerTests:TvPipNotificationTests Change-Id: I6a3e2fb96a7688814ce909f28d6d904356fad3fd
-rw-r--r--libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml9
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt4
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt89
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt45
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt92
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt44
6 files changed, 283 insertions, 0 deletions
diff --git a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
index 967e853b6a48..58fc90e4d827 100644
--- a/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
+++ b/libs/WindowManager/Shell/tests/flicker/AndroidManifest.xml
@@ -36,6 +36,15 @@
<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>
<application>
<uses-library android:name="android.test.runner"/>
+
+ <service android:name=".NotificationListener"
+ android:exported="true"
+ android:label="WMShellTestsNotificationListenerService"
+ android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE">
+ <intent-filter>
+ <action android:name="android.service.notification.NotificationListenerService" />
+ </intent-filter>
+ </service>
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
index 99f824bb8341..75b55c1e6a9f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/FlickerTestBase.kt
@@ -16,6 +16,7 @@
package com.android.wm.shell.flicker
+import android.content.pm.PackageManager
import android.os.RemoteException
import android.os.SystemClock
import android.platform.helpers.IAppHelper
@@ -41,6 +42,9 @@ abstract class FlickerTestBase {
val uiDevice by lazy {
UiDevice.getInstance(instrumentation)
}
+ val packageManager: PackageManager by lazy {
+ instrumentation.context.getPackageManager()
+ }
/**
* Build a test tag for the test
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt
new file mode 100644
index 000000000000..5c7ec30ecd3e
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/NotificationListener.kt
@@ -0,0 +1,89 @@
+/*
+ * 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
+
+import android.service.notification.NotificationListenerService
+import android.service.notification.StatusBarNotification
+import android.util.Log
+import com.android.compatibility.common.util.SystemUtil.runShellCommand
+
+class NotificationListener : NotificationListenerService() {
+ private val notifications: MutableMap<Any, StatusBarNotification> = mutableMapOf()
+
+ override fun onNotificationPosted(sbn: StatusBarNotification) {
+ if (DEBUG) Log.d(TAG, "onNotificationPosted: $sbn")
+ notifications[sbn.key] = sbn
+ }
+
+ override fun onNotificationRemoved(sbn: StatusBarNotification) {
+ if (DEBUG) Log.d(TAG, "onNotificationRemoved: $sbn")
+ notifications.remove(sbn.key)
+ }
+
+ override fun onListenerConnected() {
+ if (DEBUG) Log.d(TAG, "onListenerConnected")
+ instance = this
+ }
+
+ override fun onListenerDisconnected() {
+ if (DEBUG) Log.d(TAG, "onListenerDisconnected")
+ instance = null
+ notifications.clear()
+ }
+
+ companion object {
+ private const val DEBUG = false
+ private const val TAG = "WMShellFlickerTests_NotificationListener"
+
+ private const val CMD_NOTIFICATION_ALLOW_LISTENER = "cmd notification allow_listener %s"
+ private const val CMD_NOTIFICATION_DISALLOW_LISTENER =
+ "cmd notification disallow_listener %s"
+ private const val COMPONENT_NAME = "com.android.wm.shell.flicker/.NotificationListener"
+
+ private var instance: NotificationListener? = null
+
+ fun startNotificationListener(): Boolean {
+ if (instance != null) {
+ return true
+ }
+
+ runShellCommand(CMD_NOTIFICATION_ALLOW_LISTENER.format(COMPONENT_NAME))
+ return wait { instance != null }
+ }
+
+ fun stopNotificationListener(): Boolean {
+ if (instance == null) {
+ return true
+ }
+
+ runShellCommand(CMD_NOTIFICATION_DISALLOW_LISTENER.format(COMPONENT_NAME))
+ return wait { instance == null }
+ }
+
+ fun waitForNotificationToAppear(predicate: (StatusBarNotification) -> Boolean): Boolean {
+ return instance?.let {
+ wait { it.notifications.values.any(predicate) }
+ } ?: throw IllegalStateException("NotificationListenerService is not connected")
+ }
+
+ fun waitForNotificationToDisappear(predicate: (StatusBarNotification) -> Boolean): Boolean {
+ return instance?.let {
+ wait { it.notifications.values.none(predicate) }
+ } ?: throw IllegalStateException("NotificationListenerService is not connected")
+ }
+ }
+} \ No newline at end of file
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
new file mode 100644
index 000000000000..a6d67355f271
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/WaitUtils.kt
@@ -0,0 +1,45 @@
+/*
+ * 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
+
+import android.os.SystemClock
+
+private const val DEFAULT_TIMEOUT = 10000L
+private const val DEFAULT_POLL_INTERVAL = 1000L
+
+fun wait(condition: () -> Boolean): Boolean {
+ val (success, _) = waitForResult(extractor = condition, validator = { it })
+ return success
+}
+
+fun <R> waitForResult(
+ timeout: Long = DEFAULT_TIMEOUT,
+ interval: Long = DEFAULT_POLL_INTERVAL,
+ extractor: () -> R,
+ validator: (R) -> Boolean = { it != null }
+): Pair<Boolean, R?> {
+ val startTime = SystemClock.uptimeMillis()
+ do {
+ val result = extractor()
+ if (validator(result)) {
+ return (true to result)
+ }
+ SystemClock.sleep(interval)
+ } while (SystemClock.uptimeMillis() - startTime < timeout)
+
+ return (false to null)
+} \ 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
new file mode 100644
index 000000000000..569da1ddd953
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipNotificationTests.kt
@@ -0,0 +1,92 @@
+/*
+ * 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.app.Notification
+import android.service.notification.StatusBarNotification
+import android.view.Surface
+import androidx.test.filters.RequiresDevice
+import com.android.wm.shell.flicker.NotificationListener.Companion.startNotificationListener
+import com.android.wm.shell.flicker.NotificationListener.Companion.stopNotificationListener
+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.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
+
+/**
+ * Test Pip Notifications on TV.
+ * To run this test: `atest WMShellFlickerTests:TvPipNotificationTests`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class TvPipNotificationTests(rotationName: String, rotation: Int)
+ : TvPipTestBase(rotationName, rotation) {
+
+ @Before
+ override fun setUp() {
+ super.setUp()
+ val started = startNotificationListener()
+ if (!started) {
+ error("NotificationListener hasn't started")
+ }
+ }
+
+ @After
+ override fun tearDown() {
+ stopNotificationListener()
+ testApp.forceStop()
+ super.tearDown()
+ }
+
+ @Test
+ fun pipNotification_postedAndDismissed() {
+ testApp.launchViaIntent()
+ testApp.clickEnterPipButton()
+
+ assertTrue("Pip notification should have been posted",
+ waitForNotificationToAppear { it.isPipNotificationWithTitle(testApp.label) })
+
+ testApp.closePipWindow()
+
+ assertTrue("Pip notification should have been dismissed",
+ waitForNotificationToDisappear { it.isPipNotificationWithTitle(testApp.label) })
+ }
+
+ companion object {
+ @Parameterized.Parameters(name = "{0}")
+ @JvmStatic
+ fun getParams(): Collection<Array<Any>> {
+ val supportedRotations = intArrayOf(Surface.ROTATION_0)
+ return supportedRotations.map { arrayOf(Surface.rotationToString(it), it) }
+ }
+ }
+}
+
+private const val PIP_NOTIFICATION_TAG = "PipNotification"
+
+private val StatusBarNotification.title: String
+ get() = notification?.extras?.getString(Notification.EXTRA_TITLE) ?: ""
+
+private fun StatusBarNotification.isPipNotificationWithTitle(expectedTitle: String): Boolean =
+ tag == PIP_NOTIFICATION_TAG && title == expectedTitle \ No newline at end of file
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
new file mode 100644
index 000000000000..104248c64ddd
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/tv/TvPipTestBase.kt
@@ -0,0 +1,44 @@
+/*
+ * 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.content.pm.PackageManager.FEATURE_LEANBACK
+import android.content.pm.PackageManager.FEATURE_LEANBACK_ONLY
+import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
+import com.android.wm.shell.flicker.pip.PipTestBase
+import org.junit.After
+import org.junit.Assume
+import org.junit.Before
+
+abstract class TvPipTestBase(rotationName: String, rotation: Int)
+ : PipTestBase(rotationName, rotation) {
+
+ private val isTelevision: Boolean
+ get() = packageManager.run {
+ hasSystemFeature(FEATURE_LEANBACK) || hasSystemFeature(FEATURE_LEANBACK_ONLY)
+ }
+
+ @Before
+ open fun setUp() {
+ Assume.assumeTrue(isTelevision)
+ uiDevice.wakeUpAndGoToHomeScreen()
+ }
+
+ @After
+ open fun tearDown() {
+ }
+} \ No newline at end of file