1 /* <lambda>null2 * Copyright (C) 2022 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 18 19 import android.platform.test.annotations.FlakyTest 20 import android.platform.test.annotations.Postsubmit 21 import android.platform.test.annotations.Presubmit 22 import android.platform.test.annotations.RequiresDevice 23 import android.platform.test.annotations.RequiresFlagsDisabled 24 import android.tools.flicker.junit.FlickerParametersRunnerFactory 25 import android.tools.flicker.legacy.FlickerBuilder 26 import android.tools.flicker.legacy.LegacyFlickerTest 27 import android.tools.flicker.subject.exceptions.ExceptionMessageBuilder 28 import android.tools.flicker.subject.exceptions.IncorrectRegionException 29 import android.tools.flicker.subject.layers.LayerSubject 30 import com.android.server.wm.flicker.helpers.PipAppHelper 31 import com.android.wm.shell.Flags 32 import com.android.wm.shell.flicker.pip.common.EnterPipTransition 33 import org.junit.Assume 34 import org.junit.FixMethodOrder 35 import org.junit.Test 36 import org.junit.runner.RunWith 37 import org.junit.runners.MethodSorters 38 import org.junit.runners.Parameterized 39 import kotlin.math.abs 40 41 42 /** 43 * Test entering pip from an app via auto-enter property when navigating to home. 44 * 45 * To run this test: `atest WMShellFlickerTestsPip:AutoEnterPipOnGoToHomeTest` 46 * 47 * Actions: 48 * ``` 49 * Launch an app in full screen 50 * Select "Auto-enter PiP" radio button 51 * Press Home button or swipe up to go Home and put [pipApp] in pip mode 52 * ``` 53 * 54 * Notes: 55 * ``` 56 * 1. All assertions are inherited from [EnterPipTest] 57 * 2. Part of the test setup occurs automatically via 58 * [android.tools.flicker.legacy.runner.TransitionRunner], 59 * including configuring navigation mode, initial orientation and ensuring no 60 * apps are running before setup 61 * ``` 62 */ 63 @RequiresDevice 64 @RunWith(Parameterized::class) 65 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) 66 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 67 @RequiresFlagsDisabled(Flags.FLAG_ENABLE_PIP2) 68 open class AutoEnterPipOnGoToHomeTest(flicker: LegacyFlickerTest) : EnterPipTransition(flicker) { 69 override val pipApp: PipAppHelper = PipAppHelper(instrumentation) 70 71 override val thisTransition: FlickerBuilder.() -> Unit = { transitions { tapl.goHome() } } 72 73 override val defaultEnterPip: FlickerBuilder.() -> Unit = { 74 setup { 75 pipApp.launchViaIntent(wmHelper) 76 pipApp.enableAutoEnterForPipActivity() 77 } 78 } 79 80 override val defaultTeardown: FlickerBuilder.() -> Unit = { teardown { pipApp.exit(wmHelper) } } 81 82 private val widthNotSmallerThan: LayerSubject.(LayerSubject) -> Unit = { 83 val width = visibleRegion.region.bounds.width() 84 val otherWidth = it.visibleRegion.region.bounds.width() 85 if (width < otherWidth && abs(width - otherWidth) > EPSILON) { 86 val errorMsgBuilder = 87 ExceptionMessageBuilder() 88 .forSubject(this) 89 .forIncorrectRegion("width. $width smaller than $otherWidth") 90 .setExpected(width) 91 .setActual(otherWidth) 92 throw IncorrectRegionException(errorMsgBuilder) 93 } 94 } 95 96 @Postsubmit 97 @Test 98 override fun pipLayerReduces() { 99 Assume.assumeFalse(flicker.scenario.isGesturalNavigation) 100 flicker.assertLayers { 101 val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible } 102 pipLayerList.zipWithNext { previous, current -> 103 current.visibleRegion.notBiggerThan(previous.visibleRegion.region) 104 } 105 } 106 } 107 108 /** Checks that [pipApp] window's width is first decreasing then increasing. */ 109 @Postsubmit 110 @Test 111 fun pipLayerWidthDecreasesThenIncreases() { 112 Assume.assumeTrue(flicker.scenario.isGesturalNavigation) 113 flicker.assertLayers { 114 val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible } 115 var previousLayer = pipLayerList[0] 116 var currentLayer = previousLayer 117 var i = 0 118 invoke("layer area is decreasing") { 119 if (i < pipLayerList.size - 1) { 120 previousLayer = currentLayer 121 currentLayer = pipLayerList[++i] 122 previousLayer.widthNotSmallerThan(currentLayer) 123 } 124 }.then().invoke("layer are is increasing", true /* isOptional */) { 125 if (i < pipLayerList.size - 1) { 126 previousLayer = currentLayer 127 currentLayer = pipLayerList[++i] 128 currentLayer.widthNotSmallerThan(previousLayer) 129 } 130 } 131 } 132 } 133 134 /** Checks that [pipApp] window is animated towards default position in right bottom corner */ 135 @FlakyTest(bugId = 255578530) 136 @Test 137 fun pipLayerMovesTowardsRightBottomCorner() { 138 // in gestural nav the swipe makes PiP first go upwards 139 Assume.assumeFalse(flicker.scenario.isGesturalNavigation) 140 flicker.assertLayers { 141 val pipLayerList = this.layers { pipApp.layerMatchesAnyOf(it) && it.isVisible } 142 // Pip animates towards the right bottom corner, but because it is being resized at the 143 // same time, it is possible it shrinks first quickly below the default position and get 144 // moved up after that in just few last frames 145 pipLayerList.zipWithNext { previous, current -> 146 current.visibleRegion.isToTheRightBottom(previous.visibleRegion.region, 3) 147 } 148 } 149 } 150 151 @Presubmit 152 @Test 153 override fun focusChanges() { 154 // in gestural nav the focus goes to different activity on swipe up 155 Assume.assumeFalse(flicker.scenario.isGesturalNavigation) 156 super.focusChanges() 157 } 158 159 @FlakyTest(bugId = 289943985) 160 @Test 161 override fun visibleLayersShownMoreThanOneConsecutiveEntry() { 162 super.visibleLayersShownMoreThanOneConsecutiveEntry() 163 } 164 165 companion object { 166 // TODO(b/363080056): A margin of error allowed on certain layer size calculations. 167 const val EPSILON = 1 168 } 169 } 170