diff options
| author | 2023-07-10 18:54:29 +0000 | |
|---|---|---|
| committer | 2023-07-10 18:54:29 +0000 | |
| commit | b72062c607cbe2b8b4a1380d78934b8c08ecc3ec (patch) | |
| tree | 43feb397fe9c150a37a4332af400db4db0fd19f6 | |
| parent | 5f09337381f766437619ed459bdeb8e07a03f190 (diff) | |
| parent | ecc928b7516528d7afb3c442529910282f655b27 (diff) | |
Merge "[AE Flicker Test] From Activity A launch a trampoline Activity, expect to finish in a split A|B" into udc-qpr-dev
7 files changed, 318 insertions, 3 deletions
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt new file mode 100644 index 000000000000..c05dc324ac9e --- /dev/null +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenTrampolineActivityTest.kt @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2023 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.server.wm.flicker.activityembedding + +import android.platform.test.annotations.Presubmit +import android.tools.common.datatypes.Rect +import android.tools.common.datatypes.Region +import android.tools.common.flicker.subject.region.RegionSubject +import android.tools.common.traces.component.ComponentNameMatcher +import android.tools.device.flicker.junit.FlickerParametersRunnerFactory +import android.tools.device.flicker.legacy.FlickerBuilder +import android.tools.device.flicker.legacy.LegacyFlickerTest +import android.tools.device.flicker.legacy.LegacyFlickerTestFactory +import androidx.test.filters.RequiresDevice +import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper +import org.junit.FixMethodOrder +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.MethodSorters +import org.junit.runners.Parameterized + +/** + * Test launching a trampoline activity and resulting in a split state. + * + * Setup: Launch Activity A in fullscreen. + * + * Transitions: From A launch a trampoline Activity T, T launches secondary Activity B and + * finishes itself, end up in split A|B. + * + * To run this test: `atest FlickerTests:OpenTrampolineActivityTest` + */ +@RequiresDevice +@RunWith(Parameterized::class) +@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +class OpenTrampolineActivityTest(flicker: LegacyFlickerTest) : ActivityEmbeddingTestBase(flicker) { + override val transition: FlickerBuilder.() -> Unit = { + setup { + tapl.setExpectedRotationCheckEnabled(false) + testApp.launchViaIntent(wmHelper) + startDisplayBounds = + wmHelper.currentState.layerState.physicalDisplayBounds + ?: error("Can't get display bounds") + } + transitions { + testApp.launchTrampolineActivity(wmHelper) + } + teardown { + tapl.goHome() + testApp.exit(wmHelper) + } + } + + /** Assert the background animation layer is never visible during bounds change transition. */ + @Presubmit + @Test + fun backgroundLayerNeverVisible() { + val backgroundColorLayer = ComponentNameMatcher("", "Animation Background") + flicker.assertLayers { + isInvisible(backgroundColorLayer) + } + } + + /** Trampoline activity should finish itself before the end of this test. */ + @Presubmit + @Test + fun trampolineActivityFinishes() { + flicker.assertWmEnd { + notContains(ActivityEmbeddingAppHelper.TRAMPOLINE_ACTIVITY_COMPONENT) + } + } + + @Presubmit + @Test + fun trampolineLayerNeverVisible() { + flicker.assertLayers { + isInvisible(ActivityEmbeddingAppHelper.TRAMPOLINE_ACTIVITY_COMPONENT) + } + } + + /** Main activity is always visible throughout this test. */ + @Presubmit + @Test + fun mainActivityWindowAlwaysVisible() { + flicker.assertWm { + isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + } + } + + // TODO(b/289140963): After this is fixed, assert the main Activity window is visible + // throughout the test instead. + /** Main activity layer is visible before and after the transition. */ + @Presubmit + @Test + fun mainActivityLayerAlwaysVisible() { + flicker.assertLayersStart { + isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + } + flicker.assertLayersEnd { + isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + } + } + + /** Secondary activity is launched from the trampoline activity. */ + @Presubmit + @Test + fun secondaryActivityWindowLaunchedFromTrampoline() { + flicker.assertWm { + notContains(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + .then() + .isAppWindowInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + .then() + .isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + } + } + + /** Secondary activity is launched from the trampoline activity. */ + @Presubmit + @Test + fun secondaryActivityLayerLaunchedFromTrampoline() { + flicker.assertLayers { + isInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + .then() + .isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + } + } + + /** Main activity should go from fullscreen to being a split with secondary activity. */ + @Presubmit + @Test + fun mainActivityWindowGoesFromFullscreenToSplit() { + flicker.assertWm { + this.invoke("mainActivityStartsInFullscreen") { + it.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + .coversExactly(startDisplayBounds) + } + // Begin of transition. + .then() + .isAppWindowInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + .then() + .invoke("mainAndSecondaryInSplit") { + val mainActivityRegion = + RegionSubject( + it.visibleRegion( + ActivityEmbeddingAppHelper + .MAIN_ACTIVITY_COMPONENT).region, + it.timestamp) + val secondaryActivityRegion = + RegionSubject( + it.visibleRegion( + ActivityEmbeddingAppHelper + .SECONDARY_ACTIVITY_COMPONENT).region, + it.timestamp) + check { "height" } + .that(mainActivityRegion.region.height) + .isEqual(secondaryActivityRegion.region.height) + check { "width" } + .that(mainActivityRegion.region.width) + .isEqual(secondaryActivityRegion.region.width) + mainActivityRegion + .plus(secondaryActivityRegion.region) + .coversExactly(startDisplayBounds) + } + } + } + + /** Main activity should go from fullscreen to being a split with secondary activity. */ + @Presubmit + @Test + fun mainActivityLayerGoesFromFullscreenToSplit() { + flicker.assertLayers { + this.invoke("mainActivityStartsInFullscreen") { + it.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + .coversExactly(startDisplayBounds) + } + .then() + .isInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + .then() + .isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + } + flicker.assertLayersEnd { + val leftLayerRegion = visibleRegion( + ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) + val rightLayerRegion = + visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) + // Compare dimensions of two splits, given we're using default split attributes, + // both activities take up the same visible size on the display. + check { "height" } + .that(leftLayerRegion.region.height) + .isEqual(rightLayerRegion.region.height) + check { "width" } + .that(leftLayerRegion.region.width) + .isEqual(rightLayerRegion.region.width) + leftLayerRegion.notOverlaps(rightLayerRegion.region) + // Layers of two activities sum to be fullscreen size on display. + leftLayerRegion.plus(rightLayerRegion.region).coversExactly(startDisplayBounds) + } + } + + companion object { + /** {@inheritDoc} */ + private var startDisplayBounds = Rect.EMPTY + + /** + * Creates the test configurations. + * + * See [LegacyFlickerTestFactory.nonRotationTests] for configuring screen orientation and + * navigation modes. + */ + @Parameterized.Parameters(name = "{0}") + @JvmStatic + fun getParams() = LegacyFlickerTestFactory.nonRotationTests() + } +}
\ No newline at end of file diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt index ced7a1ec368c..eac88132d410 100644 --- a/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt +++ b/tests/FlickerTests/src/com/android/server/wm/flicker/helpers/ActivityEmbeddingAppHelper.kt @@ -77,6 +77,25 @@ constructor( } /** + * Clicks the button to launch the trampoline activity, which should launch the secondary + * activity and finish itself. + */ + fun launchTrampolineActivity(wmHelper: WindowManagerStateHelper) { + val launchButton = + uiDevice.wait( + Until.findObject(By.res(getPackage(), "launch_trampoline_button")), + FIND_TIMEOUT + ) + require(launchButton != null) { "Can't find launch trampoline activity button on screen." } + launchButton.click() + wmHelper + .StateSyncBuilder() + .withActivityState(SECONDARY_ACTIVITY_COMPONENT, PlatformConsts.STATE_RESUMED) + .withActivityRemoved(TRAMPOLINE_ACTIVITY_COMPONENT) + .waitForAndVerify() + } + + /** * Clicks the button to finishes the secondary activity launched through * [launchSecondaryActivity], waits for the main activity to resume. */ @@ -197,6 +216,9 @@ constructor( ActivityOptions.ActivityEmbedding.PlaceholderSecondaryActivity.COMPONENT .toFlickerComponent() + val TRAMPOLINE_ACTIVITY_COMPONENT = + ActivityOptions.ActivityEmbedding.TrampolineActivity.COMPONENT.toFlickerComponent() + @JvmStatic fun getWindowExtensions(): WindowExtensions? { try { diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml index 7a2e74bdb8e7..68ae806f3c8b 100644 --- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml +++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml @@ -193,6 +193,14 @@ </intent-filter> </activity> <activity + android:name=".ActivityEmbeddingTrampolineActivity" + android:label="ActivityEmbedding Trampoline" + android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding" + android:theme="@style/CutoutShortEdges" + android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout" + android:exported="false"> + </activity> + <activity android:name=".ActivityEmbeddingSecondaryActivity" android:label="ActivityEmbedding Secondary" android:taskAffinity="com.android.server.wm.flicker.testapp.ActivityEmbedding" diff --git a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml index b9d789b73732..e32a7092bf5d 100644 --- a/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml +++ b/tests/FlickerTests/test-apps/flickerapp/res/layout/activity_embedding_main_layout.xml @@ -60,4 +60,12 @@ android:tag="RIGHT_TO_LEFT" android:text="Launch Placeholder Split in RTL" /> + <Button + android:id="@+id/launch_trampoline_button" + android:layout_width="wrap_content" + android:layout_height="48dp" + android:onClick="launchTrampolineActivity" + android:tag="LEFT_TO_RIGHT" + android:text="Launch Trampoline Activity" /> + </LinearLayout> diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java index 817c79c9831f..3b1a8599f3e1 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingMainActivity.java @@ -16,14 +16,12 @@ package com.android.server.wm.flicker.testapp; - +import androidx.annotation.NonNull; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; -import com.android.server.wm.flicker.helpers.ActivityEmbeddingAppHelper; -import androidx.annotation.NonNull; import androidx.window.embedding.ActivityFilter; import androidx.window.embedding.ActivityRule; import androidx.window.embedding.EmbeddingAspectRatio; @@ -59,6 +57,15 @@ public class ActivityEmbeddingMainActivity extends Activity { mRuleController = RuleController.getInstance(this); } + /** R.id.launch_trampoline_button onClick */ + public void launchTrampolineActivity(View view) { + final String layoutDirection = view.getTag().toString(); + mRuleController.clearRules(); + mRuleController.addRule(createSplitPairRules(layoutDirection)); + startActivity(new Intent().setComponent( + ActivityOptions.ActivityEmbedding.TrampolineActivity.COMPONENT)); + } + /** R.id.launch_secondary_activity_button onClick */ public void launchSecondaryActivity(View view) { final String layoutDirection = view.getTag().toString(); diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingTrampolineActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingTrampolineActivity.java new file mode 100644 index 000000000000..67eac2ea1730 --- /dev/null +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingTrampolineActivity.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2023 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.server.wm.flicker.testapp; + +import android.app.Activity; +import android.content.Intent; +import android.os.Bundle; + +/** + * A Trampoline Activity that launches {@link ActivityEmbeddingSecondaryActivity} and then + * finishes itself. + */ +public class ActivityEmbeddingTrampolineActivity extends Activity { + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // Trampoline activity doesn't have a view. + startActivity(new Intent().setComponent( + ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT)); + finish(); + } +} diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java index d84ac427f027..95c86acb9ee9 100644 --- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java +++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityOptions.java @@ -122,6 +122,12 @@ public class ActivityOptions { public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE, FLICKER_APP_PACKAGE + ".ActivityEmbeddingPlaceholderSecondaryActivity"); } + + public static class TrampolineActivity { + public static final String LABEL = "ActivityEmbeddingTrampolineActivity"; + public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE, + FLICKER_APP_PACKAGE + ".ActivityEmbeddingTrampolineActivity"); + } } public static class Notification { |