1 /* 2 * Copyright (C) 2023 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.server.wm.flicker.activityembedding.splitscreen 18 19 import android.graphics.Rect 20 import android.platform.test.annotations.Presubmit 21 import android.platform.test.annotations.RequiresDevice 22 import android.tools.flicker.junit.FlickerParametersRunnerFactory 23 import android.tools.flicker.legacy.FlickerBuilder 24 import android.tools.flicker.legacy.LegacyFlickerTest 25 import android.tools.flicker.legacy.LegacyFlickerTestFactory 26 import android.tools.traces.parsers.toFlickerComponent 27 import androidx.test.filters.FlakyTest 28 import com.android.server.wm.flicker.activityembedding.ActivityEmbeddingTestBase 29 import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper 30 import com.android.server.wm.flicker.testapp.ActivityOptions 31 import com.android.wm.shell.flicker.utils.SPLIT_SCREEN_DIVIDER_COMPONENT 32 import com.android.wm.shell.flicker.utils.SplitScreenUtils 33 import com.android.wm.shell.flicker.utils.appWindowIsVisibleAtEnd 34 import com.android.wm.shell.flicker.utils.splitAppLayerBoundsIsVisibleAtEnd 35 import com.android.wm.shell.flicker.utils.splitScreenDividerBecomesVisible 36 import kotlin.math.abs 37 import org.junit.FixMethodOrder 38 import org.junit.Ignore 39 import org.junit.Test 40 import org.junit.runner.RunWith 41 import org.junit.runners.MethodSorters 42 import org.junit.runners.Parameterized 43 44 /** 45 * Test entering System SplitScreen with Activity Embedding Split and another app. 46 * 47 * Setup: Launch A|B in split and secondaryApp, return to home. Transitions: Let AE Split A|B enter 48 * splitscreen with secondaryApp. Resulting in A|B|secondaryApp. 49 * 50 * To run this test: `atest FlickerTestsActivityEmbedding:EnterSystemSplitTest` 51 */ 52 @RequiresDevice 53 @RunWith(Parameterized::class) 54 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) 55 @FixMethodOrder(MethodSorters.NAME_ASCENDING) 56 class EnterSystemSplitTest(flicker: LegacyFlickerTest) : ActivityEmbeddingTestBase(flicker) { 57 58 private val secondaryApp = SplitScreenUtils.getPrimary(instrumentation) <lambda>null59 override val transition: FlickerBuilder.() -> Unit = { 60 setup { 61 testApp.launchViaIntent(wmHelper) 62 testApp.launchSecondaryActivity(wmHelper) 63 secondaryApp.launchViaIntent(wmHelper) 64 startDisplayBounds = 65 wmHelper.currentState.layerState.physicalDisplayBounds ?: error("Display not found") 66 67 // Record the displayBounds before `goHome()` in case the launcher is fixed-portrait. 68 tapl.goHome() 69 wmHelper 70 .StateSyncBuilder() 71 .withAppTransitionIdle() 72 .withHomeActivityVisible() 73 .waitForAndVerify() 74 } 75 transitions { 76 SplitScreenUtils.enterSplit( 77 wmHelper, 78 tapl, 79 device, 80 testApp, 81 secondaryApp, 82 flicker.scenario.startRotation 83 ) 84 SplitScreenUtils.waitForSplitComplete(wmHelper, testApp, secondaryApp) 85 } 86 } 87 88 @Presubmit 89 @Test splitScreenDividerBecomesVisiblenull90 fun splitScreenDividerBecomesVisible() = flicker.splitScreenDividerBecomesVisible() 91 92 @Presubmit 93 @Test 94 fun activityEmbeddingSplitLayerBecomesVisible() { 95 flicker.splitAppLayerBoundsIsVisibleAtEnd( 96 testApp, 97 landscapePosLeft = tapl.isTablet, 98 portraitPosTop = false 99 ) 100 } 101 102 @Presubmit 103 @Test activityEmbeddingSplitWindowBecomesVisiblenull104 fun activityEmbeddingSplitWindowBecomesVisible() = flicker.appWindowIsVisibleAtEnd(testApp) 105 106 @Presubmit 107 @Test 108 fun secondaryLayerBecomesVisible() { 109 flicker.splitAppLayerBoundsIsVisibleAtEnd( 110 secondaryApp, 111 landscapePosLeft = !tapl.isTablet, 112 portraitPosTop = true 113 ) 114 } 115 116 @Presubmit 117 @Test secondaryAppWindowBecomesVisiblenull118 fun secondaryAppWindowBecomesVisible() = flicker.appWindowIsVisibleAtEnd(secondaryApp) 119 120 /** 121 * After the transition there should be both ActivityEmbedding activities, 122 * SplitScreenPrimaryActivity and the system split divider on screen. Verify the layers are in 123 * expected sizes. 124 */ 125 @Presubmit 126 @Test 127 fun activityEmbeddingSplitSurfaceAreEven() { 128 flicker.assertLayersEnd { 129 val leftAELayerRegion = 130 visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) 131 val rightAELayerRegion = 132 visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) 133 val secondaryAppLayerRegion = 134 visibleRegion(ActivityOptions.SplitScreen.Primary.COMPONENT.toFlickerComponent()) 135 val systemDivider = visibleRegion(SPLIT_SCREEN_DIVIDER_COMPONENT) 136 leftAELayerRegion 137 .plus(rightAELayerRegion.region) 138 .plus(secondaryAppLayerRegion.region) 139 .plus(systemDivider.region) 140 .coversExactly(startDisplayBounds) 141 check { "ActivityEmbeddingSplitHeight" } 142 .that(leftAELayerRegion.region.bounds.height()) 143 .isEqual(rightAELayerRegion.region.bounds.height()) 144 check { "ActivityEmbeddingSplitWidth" } 145 .that( 146 abs( 147 leftAELayerRegion.region.bounds.width() - 148 rightAELayerRegion.region.bounds.width() 149 ) 150 ) 151 .isLower(2) 152 } 153 } 154 155 /** Verify the windows are in expected sizes. */ 156 @Presubmit 157 @Test activityEmbeddingSplitWindowsAreEvennull158 fun activityEmbeddingSplitWindowsAreEven() { 159 flicker.assertWmEnd { 160 val leftAEWindowRegion = 161 visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) 162 val rightAEWindowRegion = 163 visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) 164 check { "ActivityEmbeddingSplitHeight" } 165 .that(leftAEWindowRegion.region.bounds.height()) 166 .isEqual(rightAEWindowRegion.region.bounds.height()) 167 check { "ActivityEmbeddingSplitWidth" } 168 .that( 169 abs( 170 leftAEWindowRegion.region.bounds.width() - 171 rightAEWindowRegion.region.bounds.width() 172 ) 173 ) 174 .isLower(2) 175 } 176 } 177 178 @Ignore("Not applicable to this CUJ.") visibleLayersShownMoreThanOneConsecutiveEntrynull179 override fun visibleLayersShownMoreThanOneConsecutiveEntry() {} 180 181 @FlakyTest(bugId = 342596801) entireScreenCoverednull182 override fun entireScreenCovered() = super.entireScreenCovered() 183 184 @FlakyTest(bugId = 342596801) 185 override fun visibleWindowsShownMoreThanOneConsecutiveEntry() = 186 super.visibleWindowsShownMoreThanOneConsecutiveEntry() 187 188 companion object { 189 /** {@inheritDoc} */ 190 private var startDisplayBounds = Rect() 191 /** 192 * Creates the test configurations. 193 * 194 * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and 195 * navigation modes. 196 */ 197 @Parameterized.Parameters(name = "{0}") 198 @JvmStatic 199 fun getParams() = LegacyFlickerTestFactory.nonRotationTests() 200 } 201 } 202