Add CTS test for recents virtual device policy

Bug: 267176019
Test: atest RecentTasksTest
Change-Id: I65ac0665e1b651212eaaf0bc28238217253d19ac
diff --git a/tests/tests/virtualdevice/src/android/virtualdevice/cts/RecentTasksTest.java b/tests/tests/virtualdevice/src/android/virtualdevice/cts/RecentTasksTest.java
new file mode 100644
index 0000000..0501797
--- /dev/null
+++ b/tests/tests/virtualdevice/src/android/virtualdevice/cts/RecentTasksTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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 android.virtualdevice.cts;
+
+import static android.Manifest.permission.ACTIVITY_EMBEDDING;
+import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
+import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
+import static android.Manifest.permission.CREATE_VIRTUAL_DEVICE;
+import static android.Manifest.permission.REAL_GET_TASKS;
+import static android.Manifest.permission.WAKE_LOCK;
+import static android.app.PendingIntent.FLAG_IMMUTABLE;
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
+import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
+import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
+import static android.virtualdevice.cts.util.TestAppHelper.MAIN_ACTIVITY_COMPONENT;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assume.assumeNotNull;
+import static org.junit.Assume.assumeTrue;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.timeout;
+import static org.mockito.Mockito.verify;
+
+import static java.lang.Integer.MAX_VALUE;
+
+import android.app.ActivityManager;
+import android.app.PendingIntent;
+import android.companion.virtual.VirtualDeviceManager;
+import android.companion.virtual.VirtualDeviceManager.VirtualDevice;
+import android.companion.virtual.VirtualDeviceParams;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.VirtualDisplay;
+import android.hardware.display.VirtualDisplayConfig;
+import android.platform.test.annotations.AppModeFull;
+import android.virtualdevice.cts.common.FakeAssociationRule;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.compatibility.common.util.AdoptShellPermissionsRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.function.IntConsumer;
+
+@RunWith(AndroidJUnit4.class)
+@AppModeFull(reason = "VirtualDeviceManager cannot be accessed by instant apps")
+public class RecentTasksTest {
+    private static final VirtualDisplayConfig VIRTUAL_DISPLAY_CONFIG =
+            new VirtualDisplayConfig.Builder("testDisplay", 100, 100, 100).setFlags(
+                    DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED).build();
+
+    @Rule
+    public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
+            InstrumentationRegistry.getInstrumentation().getUiAutomation(),
+            ACTIVITY_EMBEDDING,
+            ADD_ALWAYS_UNLOCKED_DISPLAY,
+            ADD_TRUSTED_DISPLAY,
+            CREATE_VIRTUAL_DEVICE,
+            REAL_GET_TASKS,
+            WAKE_LOCK);
+
+    @Rule
+    public FakeAssociationRule mFakeAssociationRule = new FakeAssociationRule();
+    private VirtualDeviceManager mVirtualDeviceManager;
+    private ActivityManager mActivityManager;
+    @Mock
+    private IntConsumer mLaunchCompleteListener;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        Context context = getApplicationContext();
+        final PackageManager packageManager = context.getPackageManager();
+        assumeTrue(packageManager.hasSystemFeature(PackageManager.FEATURE_COMPANION_DEVICE_SETUP));
+        assumeTrue(packageManager.hasSystemFeature(
+                PackageManager.FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS));
+        mVirtualDeviceManager = context.getSystemService(VirtualDeviceManager.class);
+        assumeNotNull(mVirtualDeviceManager);
+        mActivityManager = context.getSystemService(ActivityManager.class);
+    }
+
+    @Test
+    public void activityLaunchedOnVdmWithDefaultRecentPolicy_includedInRecents() {
+        try (VirtualDevice virtualDevice = createVirtualDeviceWithRecentsPolicy(
+                DEVICE_POLICY_DEFAULT)) {
+            VirtualDisplay virtualDisplay = virtualDevice.createVirtualDisplay(
+                    VIRTUAL_DISPLAY_CONFIG, /*executor=*/null, /*callback=*/null);
+
+            launchTestActivity(virtualDevice, virtualDisplay);
+
+            assertThat(
+                    mActivityManager.getRecentTasks(MAX_VALUE, /*flags=*/0).stream().anyMatch(
+                            RecentTasksTest::hasTestActivityComponentIntent)).isTrue();
+        }
+    }
+
+    @Test
+    public void activityLaunchedOnVdmWithCustomRecentPolicy_excludedFromRecents() {
+        try (VirtualDevice virtualDevice = createVirtualDeviceWithRecentsPolicy(
+                DEVICE_POLICY_CUSTOM)) {
+            VirtualDisplay virtualDisplay = virtualDevice.createVirtualDisplay(
+                    VIRTUAL_DISPLAY_CONFIG, /*executor=*/null, /*callback=*/null);
+
+            launchTestActivity(virtualDevice, virtualDisplay);
+
+            assertThat(
+                    mActivityManager.getRecentTasks(MAX_VALUE, /*flags=*/0).stream().anyMatch(
+                            RecentTasksTest::hasTestActivityComponentIntent)).isFalse();
+        }
+    }
+
+    private void launchTestActivity(VirtualDevice virtualDevice, VirtualDisplay virtualDisplay) {
+        Intent intent = new Intent()
+                .setComponent(MAIN_ACTIVITY_COMPONENT)
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+        virtualDevice.launchPendingIntent(virtualDisplay.getDisplay().getDisplayId(),
+                PendingIntent.getActivity(getApplicationContext(),
+                        MAIN_ACTIVITY_COMPONENT.hashCode(), intent,
+                        FLAG_IMMUTABLE | FLAG_UPDATE_CURRENT),
+                Runnable::run, mLaunchCompleteListener);
+
+        verify(mLaunchCompleteListener, timeout(1000)).accept(
+                eq(VirtualDeviceManager.LAUNCH_SUCCESS));
+    }
+
+    private static boolean hasTestActivityComponentIntent(
+            ActivityManager.RecentTaskInfo recentTaskInfo) {
+        return recentTaskInfo.baseIntent != null && MAIN_ACTIVITY_COMPONENT.equals(
+                recentTaskInfo.baseIntent.getComponent());
+    }
+
+    private VirtualDevice createVirtualDeviceWithRecentsPolicy(
+            @VirtualDeviceParams.DevicePolicy int recentsPolicy) {
+        return mVirtualDeviceManager.createVirtualDevice(
+                mFakeAssociationRule.getAssociationInfo().getId(),
+                new VirtualDeviceParams.Builder().setDevicePolicy(POLICY_TYPE_RECENTS,
+                        recentsPolicy).build());
+    }
+}