Merge "Add ActivityEmbeddingLaunchTests#testPrimaryActivityLaunchToSideClearTop" into sc-v2-dev
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java
index eae808a..b5c1d3f7 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ActivityEmbeddingLaunchTests.java
@@ -22,6 +22,8 @@
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.createWildcardSplitPairRule;
import static android.server.wm.jetpack.utils.ActivityEmbeddingUtil.startActivityAndVerifySplit;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assume.assumeNotNull;
import android.app.Activity;
@@ -29,7 +31,7 @@
import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
import android.server.wm.jetpack.utils.TestActivityWithId;
import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
-import android.server.wm.jetpack.utils.TestFirstValueConsumer;
+import android.server.wm.jetpack.utils.TestValueCountConsumer;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.window.extensions.WindowExtensions;
@@ -56,7 +58,7 @@
public class ActivityEmbeddingLaunchTests extends WindowManagerJetpackTestBase {
private ActivityEmbeddingComponent mActivityEmbeddingComponent;
- private TestFirstValueConsumer<List<SplitInfo>> mSplitInfoConsumer;
+ private TestValueCountConsumer<List<SplitInfo>> mSplitInfoConsumer;
@Before
public void setUp() {
@@ -71,7 +73,7 @@
}
});
assumeNotNull(mActivityEmbeddingComponent);
- mSplitInfoConsumer = new TestFirstValueConsumer<>();
+ mSplitInfoConsumer = new TestValueCountConsumer<>();
mActivityEmbeddingComponent.setSplitInfoCallback(mSplitInfoConsumer);
}
@@ -89,8 +91,54 @@
// all successfully split with the primary activity.
final int numActivitiesToLaunch = 4;
for (int i = 0; i < numActivitiesToLaunch; i++) {
- Activity secondaryActivity = startActivityAndVerifySplit(mSplitInfoConsumer,
- primaryActivity, TestActivityWithId.class, splitPairRule, Integer.toString(i));
+ Activity secondaryActivity = startActivityAndVerifySplit(primaryActivity,
+ TestActivityWithId.class, splitPairRule,
+ Integer.toString(i) /* secondActivityId */, mSplitInfoConsumer);
}
}
+
+ /**
+ * Tests launching activities to the side from the primary activity where the secondary stack
+ * is cleared after each launch.
+ */
+ @Test
+ public void testPrimaryActivityLaunchToSideClearTop() {
+ Activity primaryActivity = startActivityNewTask(TestConfigChangeHandlingActivity.class);
+
+ SplitPairRule splitPairRule = createWildcardSplitPairRule(true /* shouldClearTop */);
+ mActivityEmbeddingComponent.setEmbeddingRules(Collections.singleton(splitPairRule));
+
+ Activity secondaryActivity = startActivityAndVerifySplit(primaryActivity,
+ TestActivityWithId.class, splitPairRule,
+ "initialSecondaryActivity" /* secondActivityId */, mSplitInfoConsumer);
+
+ // Launch multiple activities to the side from the primary activity and verify that they
+ // all successfully split with the primary activity and that the previous secondary activity
+ // is finishing.
+ final int numActivitiesToLaunch = 4;
+ Activity prevSecondaryActivity;
+ for (int i = 0; i < numActivitiesToLaunch; i++) {
+ prevSecondaryActivity = secondaryActivity;
+ // Expect the split info consumer to return a value after the 3rd callback because the
+ // 1st callback will return empty split states due to clearing the previous secondary
+ // container, the 2nd callback will return a non-empty primary container with an empty
+ // secondary container because the primary container was just registered, and finally
+ // the 3rd callback will contain the secondary activity in the secondary container.
+ secondaryActivity = startActivityAndVerifySplit(primaryActivity,
+ TestActivityWithId.class, splitPairRule,
+ Integer.toString(i) /* secondActivityId */, mSplitInfoConsumer,
+ 3 /* expectedCallbackCount */);
+ // The previous secondary activity should be finishing because shouldClearTop was set
+ // to true, which clears the secondary container before launching the next secondary
+ // activity.
+ assertTrue(prevSecondaryActivity.isFinishing());
+ }
+
+ // Verify that the last reported split info only contains the final split
+ final List<SplitInfo> lastReportedSplitInfo = mSplitInfoConsumer.getLastReportedValue();
+ assertEquals(1, lastReportedSplitInfo.size());
+ final SplitInfo splitInfo = lastReportedSplitInfo.get(0);
+ assertEquals(1, splitInfo.getPrimaryActivityStack().getActivities().size());
+ assertEquals(1, splitInfo.getSecondaryActivityStack().getActivities().size());
+ }
}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
index 0ff4fa3..d8c804f 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/ExtensionWindowLayoutComponentTest.java
@@ -58,7 +58,7 @@
import android.server.wm.jetpack.utils.WindowManagerJetpackTestBase;
import android.server.wm.jetpack.utils.TestActivity;
import android.server.wm.jetpack.utils.TestConfigChangeHandlingActivity;
-import android.server.wm.jetpack.utils.TestFirstValueConsumer;
+import android.server.wm.jetpack.utils.TestValueCountConsumer;
import android.platform.test.annotations.Presubmit;
import androidx.annotation.NonNull;
@@ -113,8 +113,8 @@
@Test
public void testWindowLayoutComponent_WindowLayoutInfoListener() {
- TestFirstValueConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
- new TestFirstValueConsumer<>();
+ TestValueCountConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
+ new TestValueCountConsumer<>();
// Test that adding and removing callback succeeds
mWindowLayoutComponent.addWindowLayoutInfoListener(mActivity, windowLayoutInfoConsumer);
mWindowLayoutComponent.removeWindowLayoutInfoListener(windowLayoutInfoConsumer);
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
index 4f8e118..fbb2a31 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ActivityEmbeddingUtil.java
@@ -70,7 +70,7 @@
public static final float DEFAULT_SPLIT_RATIO = 0.5f;
@NonNull
- public static SplitPairRule createWildcardSplitPairRule() {
+ public static SplitPairRule createWildcardSplitPairRule(boolean shouldClearTop) {
// Any activity be split with any activity
final Predicate<Pair<Activity, Activity>> activityPairPredicate =
activityActivityPair -> true;
@@ -82,14 +82,21 @@
// Build the split pair rule
return new SplitPairRule.Builder(activityPairPredicate,
activityIntentPredicate, parentWindowMetricsPredicate).setSplitRatio(
- DEFAULT_SPLIT_RATIO).build();
+ DEFAULT_SPLIT_RATIO).setShouldClearTop(shouldClearTop).build();
}
- public static Activity startActivityAndVerifySplit(
- TestFirstValueConsumer<List<SplitInfo>> splitInfoConsumer, Activity primaryActivity,
- Class secondActivityClass, SplitPairRule splitPairRule, String secondActivityId) {
- // Must reset consumer so that most recent split info update can be received
- splitInfoConsumer.reset();
+ @NonNull
+ public static SplitPairRule createWildcardSplitPairRule() {
+ return createWildcardSplitPairRule(false /* shouldClearTop */);
+ }
+
+ public static Activity startActivityAndVerifySplit(@NonNull Activity primaryActivity,
+ @NonNull Class secondActivityClass, @NonNull SplitPairRule splitPairRule,
+ @NonNull String secondActivityId,
+ @NonNull TestValueCountConsumer<List<SplitInfo>> splitInfoConsumer,
+ int expectedCallbackCount) {
+ // Set the expected callback count
+ splitInfoConsumer.setCount(expectedCallbackCount);
// Start second activity
startActivityFromActivity(primaryActivity, secondActivityClass, secondActivityId);
@@ -100,10 +107,6 @@
activeSplitStates = splitInfoConsumer.waitAndGet();
} catch (InterruptedException e) {
fail("startActivityAndVerifySplit() InterruptedException");
- } catch (ExecutionException e) {
- fail("startActivityAndVerifySplit() ExecutionException");
- } catch (TimeoutException e) {
- fail("startActivityAndVerifySplit() TimeoutException");
}
// Get second activity from split info
@@ -117,6 +120,14 @@
return secondActivity;
}
+ public static Activity startActivityAndVerifySplit(@NonNull Activity primaryActivity,
+ @NonNull Class secondActivityClass, @NonNull SplitPairRule splitPairRule,
+ @NonNull String secondActivityId,
+ @NonNull TestValueCountConsumer<List<SplitInfo>> splitInfoConsumer) {
+ return startActivityAndVerifySplit(primaryActivity, secondActivityClass, splitPairRule,
+ secondActivityId, splitInfoConsumer, 1 /* expectedCallbackCount */);
+ }
+
@Nullable
public static Activity getSecondActivity(@NonNull List<SplitInfo> activeSplitStates,
@NonNull Activity primaryActivity, @NonNull String secondaryClassId) {
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
index f0886de..a3e682b 100644
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/ExtensionUtil.java
@@ -114,8 +114,8 @@
if (windowLayoutComponent == null) {
return null;
}
- TestFirstValueConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
- new TestFirstValueConsumer<>();
+ TestValueCountConsumer<WindowLayoutInfo> windowLayoutInfoConsumer =
+ new TestValueCountConsumer<>();
windowLayoutComponent.addWindowLayoutInfoListener(activity, windowLayoutInfoConsumer);
return windowLayoutInfoConsumer.waitAndGet();
}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestFirstValueConsumer.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestFirstValueConsumer.java
deleted file mode 100644
index 2c7a27a..0000000
--- a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestFirstValueConsumer.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2021 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 android.server.wm.jetpack.utils;
-
-import androidx.annotation.Nullable;
-
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.function.Consumer;
-
-/**
- * Consumer that provides a simple way to wait for a value to be received within a timeout and then
- * return it.
- */
-public class TestFirstValueConsumer<T> implements Consumer<T> {
-
- private static final long TIMEOUT_MS = 3000;
-
- CompletableFuture<T> mFuture;
-
- public TestFirstValueConsumer() {
- reset();
- }
-
- @Override
- public void accept(T value) {
- mFuture.complete(value);
- }
-
- public void reset() {
- mFuture = new CompletableFuture<T>();
- }
-
- @Nullable
- public T waitAndGet()
- throws ExecutionException, InterruptedException, TimeoutException {
- return mFuture.get(TIMEOUT_MS, TimeUnit.MILLISECONDS);
- }
-}
diff --git a/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java
new file mode 100644
index 0000000..4ebeac4
--- /dev/null
+++ b/tests/framework/base/windowmanager/jetpack/src/android/server/wm/jetpack/utils/TestValueCountConsumer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2021 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 android.server.wm.jetpack.utils;
+
+import androidx.annotation.Nullable;
+
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+
+/**
+ * Consumer that provides a simple way to wait for a specific count of values to be received within
+ * a timeout and then return the last value.
+ */
+public class TestValueCountConsumer<T> implements Consumer<T> {
+
+ private static final long TIMEOUT_MS = 3000;
+ private static final int DEFAULT_COUNT = 1;
+ private int mCount = DEFAULT_COUNT;
+ private LinkedBlockingQueue<T> mLinkedBlockingQueue;
+ private T mLastReportedValue;
+
+ public TestValueCountConsumer() {
+ mLinkedBlockingQueue = new LinkedBlockingQueue<>();
+ }
+
+ @Override
+ public void accept(T value) {
+ // Asynchronously offer value to queue
+ mLinkedBlockingQueue.offer(value);
+ }
+
+ public void setCount(int count) {
+ mCount = count;
+ }
+
+ @Nullable
+ public T waitAndGet() throws InterruptedException {
+ T value = null;
+ for (int i = 0; i < mCount; i++) {
+ value = mLinkedBlockingQueue.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS);
+ }
+ mLastReportedValue = value;
+ return value;
+ }
+
+ @Nullable
+ public T getLastReportedValue() {
+ return mLastReportedValue;
+ }
+}