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

Commit 5902a6dc authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add tests for TV Pip notification intents"

parents c33bf845 26fd1f19
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