diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
new file mode 100644
index 0000000000000..43f4ce9b4f6b5
--- /dev/null
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/activityembedding/open/OpenThirdActivityOverSplitTest.kt
@@ -0,0 +1,170 @@
+/*
+ * 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.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 secondary activity over an existing split. By default the new secondary
+ * activity will stack over the previous secondary activity.
+ *
+ * Setup: From Activity A launch a split A|B.
+ *
+ * Transitions: Let B start C, expect C to cover B and end up in split A|C.
+ *
+ * To run this test: `atest FlickerTests:OpenThirdActivityOverSplitTest`
+ */
+@RequiresDevice
+@RunWith(Parameterized::class)
+@Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+class OpenThirdActivityOverSplitTest (flicker: LegacyFlickerTest) :
+ ActivityEmbeddingTestBase(flicker) {
+ /** {@inheritDoc} */
+ override val transition: FlickerBuilder.() -> Unit = {
+ setup {
+ tapl.setExpectedRotationCheckEnabled(false)
+ // Launch a split.
+ testApp.launchViaIntent(wmHelper)
+ testApp.launchSecondaryActivity(wmHelper)
+
+ startDisplayBounds =
+ wmHelper.currentState.layerState.physicalDisplayBounds
+ ?: error("Can't get display bounds")
+ }
+ transitions {
+ testApp.launchThirdActivity(wmHelper)
+ }
+ teardown {
+ tapl.goHome()
+ testApp.exit(wmHelper)
+ }
+ }
+
+ /** Main activity remains visible throughout the transition. */
+ @Presubmit
+ @Test
+ fun mainActivityWindowAlwaysVisible() {
+ flicker.assertWm { isAppWindowVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT) }
+ }
+
+ /** Main activity remains visible throughout the transition and takes up half of the screen. */
+ @Presubmit
+ @Test
+ fun mainActivityLayersAlwaysVisible() {
+ flicker.assertLayers {
+ isVisible(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+ }
+
+ flicker.assertLayersStart {
+ val display = this.entry.displays.firstOrNull { it.isOn && !it.isVirtual }
+ ?: error("No non-virtual and on display found")
+ val mainActivityRegion =
+ this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+ val secondaryActivityRegion =
+ this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ .region
+ mainActivityRegion
+ .plus(secondaryActivityRegion)
+ .coversExactly(display.layerStackSpace)
+ }
+
+ flicker.assertLayersEnd {
+ val display = this.entry.displays.firstOrNull { it.isOn && !it.isVirtual }
+ ?: error("No non-virtual and on display found")
+ val mainActivityRegion =
+ this.visibleRegion(ActivityEmbeddingAppHelper.MAIN_ACTIVITY_COMPONENT)
+ val secondaryActivityRegion =
+ this.visibleRegion(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ secondaryActivityRegion.isEmpty()
+ val thirdActivityRegion =
+ this.visibleRegion(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ mainActivityRegion
+ .plus(thirdActivityRegion.region)
+ .coversExactly(display.layerStackSpace)
+ }
+ }
+
+ /** Third activity launches during the transition and covers up secondary activity. */
+ @Presubmit
+ @Test
+ fun thirdActivityWindowLaunchesIntoSplit() {
+ flicker.assertWm {
+ isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ .isAppWindowInvisible(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ .then()
+ .isAppWindowVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ .isAppWindowVisible(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ .then()
+ .isAppWindowVisible(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ .isAppWindowInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT) // expectation
+ }
+ }
+
+ /** Third activity launches during the transition and covers up secondary activity. */
+ @Presubmit
+ @Test
+ fun thirdActivityLayerLaunchesIntoSplit() {
+ flicker.assertLayers {
+ isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ .isInvisible(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ .then()
+ .isVisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ .isVisible(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ .then()
+ .isVisible(ActivityEmbeddingAppHelper.THIRD_ACTIVITY_COMPONENT)
+ .isInvisible(ActivityEmbeddingAppHelper.SECONDARY_ACTIVITY_COMPONENT)
+ }
+ }
+
+ /** Assert the background animation layer is never visible during transition. */
+ @Presubmit
+ @Test
+ fun backgroundLayerNeverVisible() {
+ val backgroundColorLayer = ComponentNameMatcher("", "Animation Background")
+ flicker.assertLayers {
+ isInvisible(backgroundColorLayer)
+ }
+ }
+
+ 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 351eb1e5d2c37..06beec19cbf02 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
@@ -59,6 +59,23 @@ constructor(
.waitForAndVerify()
}
+ /** Clicks the button to launch a third activity over a secondary activity. */
+ fun launchThirdActivity(wmHelper: WindowManagerStateHelper) {
+ val launchButton =
+ uiDevice.wait(
+ Until.findObject(By.res(getPackage(), "launch_third_activity_button")),
+ FIND_TIMEOUT
+ )
+ require(launchButton != null) { "Can't find launch third activity button on screen." }
+ launchButton.click()
+ wmHelper
+ .StateSyncBuilder()
+ .withActivityState(MAIN_ACTIVITY_COMPONENT, PlatformConsts.STATE_RESUMED)
+ .withActivityState(SECONDARY_ACTIVITY_COMPONENT, PlatformConsts.STATE_STOPPED)
+ .withActivityState(THIRD_ACTIVITY_COMPONENT, PlatformConsts.STATE_RESUMED)
+ .waitForAndVerify()
+ }
+
/**
* Clicks the button to finishes the secondary activity launched through
* [launchSecondaryActivity], waits for the main activity to resume.
@@ -166,6 +183,9 @@ constructor(
val SECONDARY_ACTIVITY_COMPONENT =
ActivityOptions.ActivityEmbedding.SecondaryActivity.COMPONENT.toFlickerComponent()
+ val THIRD_ACTIVITY_COMPONENT =
+ ActivityOptions.ActivityEmbedding.ThirdActivity.COMPONENT.toFlickerComponent()
+
val ALWAYS_EXPAND_ACTIVITY_COMPONENT =
ActivityOptions.ActivityEmbedding.AlwaysExpandActivity.COMPONENT.toFlickerComponent()
diff --git a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
index 64302831202ee..7a2e74bdb8e7a 100644
--- a/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
+++ b/tests/FlickerTests/test-apps/flickerapp/AndroidManifest.xml
@@ -199,6 +199,13 @@
android:theme="@style/CutoutShortEdges"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:exported="false"/>
+
+
+
\ No newline at end of file
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
index 6e78750cdeeef..dc21027bc99c8 100644
--- a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingSecondaryActivity.java
@@ -17,6 +17,7 @@
package com.android.server.wm.flicker.testapp;
import android.app.Activity;
+import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
@@ -40,4 +41,9 @@ public class ActivityEmbeddingSecondaryActivity extends Activity {
}
});
}
+
+ public void launchThirdActivity(View view) {
+ startActivity(new Intent().setComponent(
+ ActivityOptions.ActivityEmbedding.ThirdActivity.COMPONENT));
+ }
}
diff --git a/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingThirdActivity.java b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingThirdActivity.java
new file mode 100644
index 0000000000000..3bd72818d8948
--- /dev/null
+++ b/tests/FlickerTests/test-apps/flickerapp/src/com/android/server/wm/flicker/testapp/ActivityEmbeddingThirdActivity.java
@@ -0,0 +1,34 @@
+/*
+ * 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.graphics.Color;
+import android.os.Bundle;
+
+/**
+ * Activity to be used also as a secondary activity to split with
+ * {@link ActivityEmbeddingMainActivity}.
+ */
+public class ActivityEmbeddingThirdActivity extends Activity {
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_embedding_base_layout);
+ findViewById(R.id.root_activity_layout).setBackgroundColor(Color.RED);
+ }
+}
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 52106189840dc..d84ac427f027e 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
@@ -99,6 +99,12 @@ public class ActivityOptions {
FLICKER_APP_PACKAGE + ".ActivityEmbeddingSecondaryActivity");
}
+ public static class ThirdActivity {
+ public static final String LABEL = "ActivityEmbeddingThirdActivity";
+ public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,
+ FLICKER_APP_PACKAGE + ".ActivityEmbeddingThirdActivity");
+ }
+
public static class AlwaysExpandActivity {
public static final String LABEL = "ActivityEmbeddingAlwaysExpandActivity";
public static final ComponentName COMPONENT = new ComponentName(FLICKER_APP_PACKAGE,