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

Commit 26fd1f19 authored by Sergey Nikolaienkov's avatar Sergey Nikolaienkov
Browse files

Add tests for TV Pip notification intents

Bug: 171520419
Test: atest WMShellFlickerTests:TvPipNotificationTests
Change-Id: I615cda0ed826d875ea8f2eed4c570280be6d6ae9
parent 757e60e0
Loading
Loading
Loading
Loading
+7 −3
Original line number Diff line number Diff line
@@ -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")
+5 −0
Original line number Diff line number Diff line
@@ -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 {
@@ -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
    }
}
+1 −2
Original line number Diff line number Diff line
@@ -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()
        }
    }
}
+57 −4
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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()
@@ -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
@@ -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
+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