1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wm.shell.flicker.pip.tv 18 19 import android.app.Instrumentation 20 import android.tools.traces.parsers.WindowManagerStateHelper 21 import androidx.test.uiautomator.By 22 import androidx.test.uiautomator.BySelector 23 import androidx.test.uiautomator.UiObject2 24 import androidx.test.uiautomator.Until 25 import com.android.server.wm.flicker.helpers.PipAppHelper 26 27 /** Helper class for PIP app on AndroidTV */ 28 open class PipAppHelperTv(instrumentation: Instrumentation) : PipAppHelper(instrumentation) { 29 private val appSelector = By.pkg(packageName).depth(0) 30 31 val ui: UiObject2? 32 get() = uiDevice.findObject(appSelector) 33 focusOnObjectnull34 private fun focusOnObject(selector: BySelector): Boolean { 35 // We expect all the focusable UI elements to be arranged in a way so that it is possible 36 // to "cycle" over all them by clicking the D-Pad DOWN button, going back up to "the top" 37 // from "the bottom". 38 repeat(FOCUS_ATTEMPTS) { 39 uiDevice.findObject(selector)?.apply { if (isFocusedOrHasFocusedChild) return true } 40 ?: error("The object we try to focus on is gone.") 41 42 uiDevice.pressDPadDown() 43 uiDevice.waitForIdle() 44 } 45 return false 46 } 47 clickObjectnull48 override fun clickObject(resId: String) { 49 val selector = By.res(packageName, resId) 50 focusOnObject(selector) || error("Could not focus on `$resId` object") 51 uiDevice.pressDPadCenter() 52 } 53 54 @Deprecated( 55 "Use PipAppHelper.closePipWindow(wmHelper) instead", 56 ReplaceWith("closePipWindow(wmHelper)") 57 ) closePipWindownull58 override fun closePipWindow() { 59 uiDevice.closeTvPipWindow() 60 } 61 62 /** Taps the pip window and dismisses it by clicking on the X button. */ closePipWindownull63 override fun closePipWindow(wmHelper: WindowManagerStateHelper) { 64 uiDevice.closeTvPipWindow() 65 66 // Wait for animation to complete. 67 wmHelper.StateSyncBuilder().withPipGone().withHomeActivityVisible().waitForAndVerify() 68 } 69 waitUntilClosednull70 fun waitUntilClosed(): Boolean { 71 val appSelector = By.pkg(packageName).depth(0) 72 return uiDevice.wait(Until.gone(appSelector), APP_CLOSE_WAIT_TIME_MS) 73 } 74 75 companion object { 76 private const val FOCUS_ATTEMPTS = 20 77 private const val APP_CLOSE_WAIT_TIME_MS = 3_000L 78 } 79 } 80