Fixes and additions to VDM unit tests
- Fix flag usage in VirtualDeviceTest
- Fix a typo in VirtualDeviceManagerTest
- Add GenericWindowPolicyControllerTest to test GWPC in isolation.
Contains a modified copy of test cases from VDMSTest to only account
for GWPC.
- Add tests for GWPC policy to block permission dialogs
- Add tests in VirtualDeviceManagerServiceTest to ensure the permission
flag behaves as expected.
Bug: 298032672
Bug: 291737919
Test: atest com.android.server.companion.virtual
Change-Id: I79b54aee75b05c60ca84490f10a23e5bee04ed3f
diff --git a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
index b56b47f..9dd0dca 100644
--- a/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
+++ b/services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java
@@ -121,7 +121,7 @@
@NonNull
@GuardedBy("mGenericWindowPolicyControllerLock")
- final ArraySet<Integer> mRunningUids = new ArraySet<>();
+ private final ArraySet<Integer> mRunningUids = new ArraySet<>();
@Nullable private final ActivityListener mActivityListener;
@Nullable private final PipBlockedCallback mPipBlockedCallback;
@Nullable private final IntentListenerCallback mIntentListenerCallback;
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
new file mode 100644
index 0000000..a7c8a6c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/GenericWindowPolicyControllerTest.java
@@ -0,0 +1,890 @@
+/*
+ * Copyright (C) 2022 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.companion.virtual;
+
+import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.WindowConfiguration;
+import android.companion.virtual.IVirtualDeviceIntentInterceptor;
+import android.companion.virtual.VirtualDeviceManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.net.Uri;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.platform.test.annotations.Presubmit;
+import android.platform.test.flag.junit.SetFlagsRule;
+import android.util.ArraySet;
+import android.view.Display;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.internal.app.BlockedAppStreamingActivity;
+
+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.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+@Presubmit
+@RunWith(AndroidJUnit4.class)
+public class GenericWindowPolicyControllerTest {
+
+ private static final int DISPLAY_ID = Display.DEFAULT_DISPLAY + 1;
+ private static final int TEST_UID = 1234567;
+ private static final String DISPLAY_CATEGORY = "com.display.category";
+ private static final String NONBLOCKED_APP_PACKAGE_NAME = "com.someapp";
+ private static final String BLOCKED_PACKAGE_NAME = "com.blockedapp";
+ private static final int FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES = 0x00000;
+ private static final String TEST_SITE = "http://test";
+ private static final ComponentName BLOCKED_APP_STREAMING_COMPONENT =
+ new ComponentName("android", BlockedAppStreamingActivity.class.getName());
+ private static final ComponentName BLOCKED_COMPONENT = new ComponentName(BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME);
+ private static final ComponentName NONBLOCKED_COMPONENT = new ComponentName(
+ NONBLOCKED_APP_PACKAGE_NAME, NONBLOCKED_APP_PACKAGE_NAME);
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ @Mock
+ private GenericWindowPolicyController.PipBlockedCallback mPipBlockedCallback;
+ @Mock
+ private VirtualDeviceManager.ActivityListener mActivityListener;
+ @Mock
+ private GenericWindowPolicyController.IntentListenerCallback mIntentListenerCallback;
+ @Mock
+ private GenericWindowPolicyController.ActivityBlockedCallback mActivityBlockedCallback;
+ @Mock
+ private GenericWindowPolicyController.RunningAppsChangedListener mRunningAppsChangedListener;
+ @Mock
+ private GenericWindowPolicyController.SecureWindowCallback mSecureWindowCallback;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void showTasksInHostDeviceRecents() {
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ gwpc.setShowInHostDeviceRecents(true);
+ assertThat(gwpc.canShowTasksInHostDeviceRecents()).isTrue();
+
+ gwpc.setShowInHostDeviceRecents(false);
+ assertThat(gwpc.canShowTasksInHostDeviceRecents()).isFalse();
+ }
+
+ @Test
+ public void containsUid() {
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ assertThat(gwpc.containsUid(TEST_UID)).isFalse();
+
+ gwpc.onRunningAppsChanged(new ArraySet<>(Arrays.asList(TEST_UID)));
+ assertThat(gwpc.containsUid(TEST_UID)).isTrue();
+
+ gwpc.onRunningAppsChanged(new ArraySet<>());
+ assertThat(gwpc.containsUid(TEST_UID)).isFalse();
+ }
+
+ @Test
+ public void isEnteringPipAllowed_falseByDefault() {
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ assertThat(gwpc.isEnteringPipAllowed(TEST_UID)).isFalse();
+ verify(mPipBlockedCallback).onEnteringPipBlocked(TEST_UID);
+ }
+
+ @Test
+ public void isEnteringPipAllowed_dpcSupportsPinned_allowed() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setSupportedWindowingModes(new HashSet<>(
+ Arrays.asList(WindowConfiguration.WINDOWING_MODE_FULLSCREEN,
+ WindowConfiguration.WINDOWING_MODE_PINNED)));
+ assertThat(gwpc.isEnteringPipAllowed(TEST_UID)).isTrue();
+ verify(mPipBlockedCallback, never()).onEnteringPipBlocked(TEST_UID);
+ }
+
+ @Test
+ public void openNonBlockedAppOnVirtualDisplay_isNotBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void activityDoesNotSupportDisplayOnRemoteDevices_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ false,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void openBlockedComponentOnVirtualDisplay_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithBlockedComponent(BLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void addActivityPolicyExemption_openBlockedOnVirtualDisplay_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+ gwpc.setActivityLaunchDefaultAllowed(true);
+ gwpc.addActivityPolicyExemption(BLOCKED_COMPONENT);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void openNotAllowedComponentOnBlocklistVirtualDisplay_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithAllowedComponent(NONBLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void addActivityPolicyExemption_openNotAllowedOnVirtualDisplay_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+ gwpc.setActivityLaunchDefaultAllowed(false);
+ gwpc.addActivityPolicyExemption(NONBLOCKED_COMPONENT);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void openAllowedComponentOnBlocklistVirtualDisplay_startsActivity() {
+ GenericWindowPolicyController gwpc = createGwpcWithAllowedComponent(NONBLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void addActivityPolicyExemption_openAllowedOnVirtualDisplay_startsActivity() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+ gwpc.setActivityLaunchDefaultAllowed(false);
+ gwpc.addActivityPolicyExemption(NONBLOCKED_COMPONENT);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_mismatchingUserHandle_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null,
+ /* uid */ UserHandle.PER_USER_RANGE + 1);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_blockedAppStreamingComponent_isNeverBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_APP_STREAMING_COMPONENT.getPackageName(),
+ BLOCKED_APP_STREAMING_COMPONENT.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_blockedAppStreamingComponentExplicitlyBlocked_isNeverBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithBlockedComponent(
+ BLOCKED_APP_STREAMING_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_APP_STREAMING_COMPONENT.getPackageName(),
+ BLOCKED_APP_STREAMING_COMPONENT.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_blockedAppStreamingComponentExemptFromStreaming_isNeverBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+ gwpc.setActivityLaunchDefaultAllowed(true);
+ gwpc.addActivityPolicyExemption(BLOCKED_APP_STREAMING_COMPONENT);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_APP_STREAMING_COMPONENT.getPackageName(),
+ BLOCKED_APP_STREAMING_COMPONENT.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_blockedAppStreamingComponentNotAllowlisted_isNeverBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithAllowedComponent(NONBLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_APP_STREAMING_COMPONENT.getPackageName(),
+ BLOCKED_APP_STREAMING_COMPONENT.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_blockedAppStreamingComponentNotExemptFromBlocklist_isNeverBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+ gwpc.setActivityLaunchDefaultAllowed(false);
+ gwpc.addActivityPolicyExemption(NONBLOCKED_COMPONENT);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_APP_STREAMING_COMPONENT.getPackageName(),
+ BLOCKED_APP_STREAMING_COMPONENT.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_customDisplayCategoryMatches_isNotBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithDisplayCategory(DISPLAY_CATEGORY);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ DISPLAY_CATEGORY);
+
+ assertActivityCanBeLaunched(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_customDisplayCategoryDoesNotMatch_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithDisplayCategory(DISPLAY_CATEGORY);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ "some.random.category");
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_crossTaskLaunch_fromDefaultDisplay_isNotBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityCanBeLaunched(gwpc, Display.DEFAULT_DISPLAY, true,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_crossTaskLaunchFromVirtualDisplay_notExplicitlyBlocked_isNotBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithCrossTaskNavigationBlockedFor(
+ BLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertActivityCanBeLaunched(gwpc, DISPLAY_ID, true,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_crossTaskLaunchFromVirtualDisplay_explicitlyBlocked_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithCrossTaskNavigationBlockedFor(
+ BLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, DISPLAY_ID, true,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_crossTaskLaunchFromVirtualDisplay_notAllowed_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithCrossTaskNavigationAllowed(
+ NONBLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, DISPLAY_ID, true,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_crossTaskLaunchFromVirtualDisplay_allowed_isNotBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithCrossTaskNavigationAllowed(
+ NONBLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityCanBeLaunched(gwpc, DISPLAY_ID, true,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_unsupportedWindowingMode_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, DISPLAY_ID, true, WindowConfiguration.WINDOWING_MODE_PINNED,
+ activityInfo);
+ }
+
+ @Test
+ public void canActivityBeLaunched_permissionComponent_isBlocked() {
+ GenericWindowPolicyController gwpc = createGwpcWithPermissionComponent(BLOCKED_COMPONENT);
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ BLOCKED_PACKAGE_NAME,
+ BLOCKED_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertActivityIsBlocked(gwpc, activityInfo);
+ }
+
+ @Test
+ public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() {
+ ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(TEST_UID));
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ gwpc.registerRunningAppsChangedListener(mRunningAppsChangedListener);
+ gwpc.onRunningAppsChanged(uids);
+
+ assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(1);
+ verify(mRunningAppsChangedListener).onRunningAppsChanged(uids);
+ }
+
+ @Test
+ public void onRunningAppsChanged_empty_onDisplayEmpty() {
+ ArraySet<Integer> uids = new ArraySet<>();
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ gwpc.onRunningAppsChanged(uids);
+
+ assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(0);
+ verify(mActivityListener).onDisplayEmpty(DISPLAY_ID);
+ }
+
+ @Test
+ public void noRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException() {
+ ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(TEST_UID));
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ gwpc.onRunningAppsChanged(uids);
+
+ assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(0);
+ verify(mRunningAppsChangedListener, never()).onRunningAppsChanged(uids);
+ }
+
+ @Test
+ public void registerUnregisterRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException() {
+ ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(TEST_UID));
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ gwpc.registerRunningAppsChangedListener(mRunningAppsChangedListener);
+ gwpc.unregisterRunningAppsChangedListener(mRunningAppsChangedListener);
+ gwpc.onRunningAppsChanged(uids);
+
+ assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(0);
+ verify(mRunningAppsChangedListener, never()).onRunningAppsChanged(uids);
+ }
+
+ @Test
+ public void canActivityBeLaunched_intentInterceptedWhenRegistered_activityNoLaunch()
+ throws RemoteException {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(TEST_SITE));
+
+ IVirtualDeviceIntentInterceptor.Stub interceptor =
+ mock(IVirtualDeviceIntentInterceptor.Stub.class);
+ doNothing().when(interceptor).onIntentIntercepted(any());
+ doReturn(interceptor).when(interceptor).asBinder();
+ doReturn(interceptor).when(interceptor).queryLocalInterface(anyString());
+
+ GenericWindowPolicyController gwpc = createGwpc();
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ // register interceptor and intercept intent
+ when(mIntentListenerCallback.shouldInterceptIntent(any(Intent.class))).thenReturn(true);
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /*isNewTask=*/false))
+ .isFalse();
+
+ // unregister interceptor and launch activity
+ when(mIntentListenerCallback.shouldInterceptIntent(any(Intent.class))).thenReturn(false);
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /*isNewTask=*/false))
+ .isTrue();
+ }
+
+ @Test
+ public void canActivityBeLaunched_noMatchIntentFilter_activityLaunches() {
+ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("testing"));
+
+ GenericWindowPolicyController gwpc = createGwpc();
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ // register interceptor with different filter
+ when(mIntentListenerCallback.shouldInterceptIntent(any(Intent.class))).thenReturn(false);
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID, /*isNewTask=*/false))
+ .isTrue();
+ verify(mIntentListenerCallback).shouldInterceptIntent(any(Intent.class));
+ }
+
+ @Test
+ public void onTopActivitychanged_null_noCallback() {
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ gwpc.onTopActivityChanged(null, 0, 0);
+ verify(mActivityListener, never())
+ .onTopActivityChanged(anyInt(), any(ComponentName.class), anyInt());
+ }
+
+ @Test
+ public void onTopActivitychanged_activityListenerCallbackObserved() {
+ int userId = 1000;
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ gwpc.onTopActivityChanged(BLOCKED_COMPONENT, 0, userId);
+ verify(mActivityListener)
+ .onTopActivityChanged(eq(DISPLAY_ID), eq(BLOCKED_COMPONENT), eq(userId));
+ }
+
+ @Test
+ public void keepActivityOnWindowFlagsChanged_noChange() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertThat(gwpc.keepActivityOnWindowFlagsChanged(activityInfo, 0, 0)).isTrue();
+
+ verify(mSecureWindowCallback, never()).onSecureWindowShown(DISPLAY_ID,
+ activityInfo.applicationInfo.uid);
+ verify(mActivityBlockedCallback, never()).onActivityBlocked(DISPLAY_ID, activityInfo);
+ }
+
+ @Test
+ public void keepActivityOnWindowFlagsChanged_flagSecure_isAllowedAfterTM() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertThat(gwpc.keepActivityOnWindowFlagsChanged(activityInfo, FLAG_SECURE, 0)).isTrue();
+
+ verify(mSecureWindowCallback).onSecureWindowShown(DISPLAY_ID,
+ activityInfo.applicationInfo.uid);
+ verify(mActivityBlockedCallback, never()).onActivityBlocked(DISPLAY_ID, activityInfo);
+ }
+
+ @Test
+ public void keepActivityOnWindowFlagsChanged_systemFlagHideNonSystemOverlayWindows_isAllowedAfterTM() {
+ GenericWindowPolicyController gwpc = createGwpc();
+ gwpc.setDisplayId(DISPLAY_ID);
+
+ ActivityInfo activityInfo = getActivityInfo(
+ NONBLOCKED_APP_PACKAGE_NAME,
+ NONBLOCKED_APP_PACKAGE_NAME,
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+
+ assertThat(gwpc.keepActivityOnWindowFlagsChanged(activityInfo, 0,
+ SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS)).isTrue();
+
+ verify(mSecureWindowCallback, never()).onSecureWindowShown(DISPLAY_ID,
+ activityInfo.applicationInfo.uid);
+ verify(mActivityBlockedCallback, never()).onActivityBlocked(DISPLAY_ID, activityInfo);
+ }
+
+ @Test
+ public void getCustomHomeComponent_noneSet() {
+ GenericWindowPolicyController gwpc = createGwpc();
+
+ assertThat(gwpc.getCustomHomeComponent()).isNull();
+ }
+
+ @Test
+ public void getCustomHomeComponent_returnsHomeComponent() {
+ GenericWindowPolicyController gwpc = createGwpcWithCustomHomeComponent(
+ NONBLOCKED_COMPONENT);
+
+ assertThat(gwpc.getCustomHomeComponent()).isEqualTo(NONBLOCKED_COMPONENT);
+ }
+
+ private GenericWindowPolicyController createGwpc() {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ mSecureWindowCallback,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private GenericWindowPolicyController createGwpcWithCustomHomeComponent(
+ ComponentName homeComponent) {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ homeComponent);
+ }
+
+ private GenericWindowPolicyController createGwpcWithBlockedComponent(
+ ComponentName blockedComponent) {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ Collections.singleton(blockedComponent),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private GenericWindowPolicyController createGwpcWithAllowedComponent(
+ ComponentName allowedComponent) {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ false,
+ /* activityPolicyExemptions= */ Collections.singleton(allowedComponent),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private GenericWindowPolicyController createGwpcWithDisplayCategory(
+ String displayCategory) {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ Collections.singleton(displayCategory),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private GenericWindowPolicyController createGwpcWithCrossTaskNavigationBlockedFor(
+ ComponentName blockedComponent) {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ true,
+ /* crossTaskNavigationExemptions= */ Collections.singleton(blockedComponent),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private GenericWindowPolicyController createGwpcWithCrossTaskNavigationAllowed(
+ ComponentName allowedComponent) {
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ false,
+ /* crossTaskNavigationExemptions= */ Collections.singleton(allowedComponent),
+ /* permissionDialogComponent= */ null,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private GenericWindowPolicyController createGwpcWithPermissionComponent(
+ ComponentName permissionComponent) {
+ //TODO instert the component
+ return new GenericWindowPolicyController(
+ 0,
+ 0,
+ /* allowedUsers= */ new ArraySet<>(getCurrentUserId()),
+ /* activityLaunchAllowedByDefault= */ true,
+ /* activityPolicyExemptions= */ new ArraySet<>(),
+ /* crossTaskNavigationAllowedByDefault= */ false,
+ /* crossTaskNavigationExemptions= */ new ArraySet<>(),
+ /* permissionDialogComponent= */ permissionComponent,
+ /* activityListener= */ mActivityListener,
+ /* pipBlockedCallback= */ mPipBlockedCallback,
+ /* activityBlockedCallback= */ mActivityBlockedCallback,
+ /* secureWindowCallback= */ null,
+ /* intentListenerCallback= */ mIntentListenerCallback,
+ /* displayCategories= */ new ArraySet<>(),
+ /* showTasksInHostDeviceRecents= */ true,
+ /* customHomeComponent= */ null);
+ }
+
+ private Set<UserHandle> getCurrentUserId() {
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ return new ArraySet<>(Arrays.asList(context.getUser()));
+ }
+
+ private ActivityInfo getActivityInfo(
+ String packageName, String name, boolean displayOnRemoteDevices,
+ String requiredDisplayCategory) {
+ return getActivityInfo(packageName, name, displayOnRemoteDevices, requiredDisplayCategory,
+ 0);
+ }
+
+ private ActivityInfo getActivityInfo(
+ String packageName, String name, boolean displayOnRemoteDevices,
+ String requiredDisplayCategory, int uid) {
+ ApplicationInfo applicationInfo = new ApplicationInfo();
+ applicationInfo.uid = uid;
+
+ ActivityInfo activityInfo = new ActivityInfo();
+ activityInfo.packageName = packageName;
+ activityInfo.name = name;
+ activityInfo.flags = displayOnRemoteDevices
+ ? FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES : FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES;
+ activityInfo.applicationInfo = applicationInfo;
+ activityInfo.requiredDisplayCategory = requiredDisplayCategory;
+ return activityInfo;
+ }
+
+ private void assertActivityCanBeLaunched(GenericWindowPolicyController gwpc,
+ ActivityInfo activityInfo) {
+ assertActivityCanBeLaunched(gwpc, DISPLAY_ID, false,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ private void assertActivityCanBeLaunched(GenericWindowPolicyController gwpc, int fromDisplay,
+ boolean isNewTask, int windowingMode, ActivityInfo activityInfo) {
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, null, windowingMode, fromDisplay,
+ isNewTask)).isTrue();
+
+ verify(mActivityBlockedCallback, never()).onActivityBlocked(fromDisplay, activityInfo);
+ verify(mIntentListenerCallback, never()).shouldInterceptIntent(any(Intent.class));
+ }
+
+ private void assertActivityIsBlocked(GenericWindowPolicyController gwpc,
+ ActivityInfo activityInfo) {
+ assertActivityIsBlocked(gwpc, DISPLAY_ID, false,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, activityInfo);
+ }
+
+ private void assertActivityIsBlocked(GenericWindowPolicyController gwpc, int fromDisplay,
+ boolean isNewTask, int windowingMode, ActivityInfo activityInfo) {
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, null, windowingMode, fromDisplay,
+ isNewTask)).isFalse();
+
+ verify(mActivityBlockedCallback).onActivityBlocked(fromDisplay, activityInfo);
+ verify(mIntentListenerCallback, never()).shouldInterceptIntent(any(Intent.class));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index 1e6306c..263d470 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -24,6 +24,7 @@
import static android.content.Context.DEVICE_ID_INVALID;
import static android.content.Intent.ACTION_VIEW;
import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES;
+import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
@@ -70,6 +71,7 @@
import android.content.IntentFilter;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
@@ -303,7 +305,7 @@
ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
- /* displayOnRemoveDevices= */ true,
+ /* displayOnRemoteDevices= */ true,
targetDisplayCategory);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -314,12 +316,12 @@
private ActivityInfo getActivityInfo(
- String packageName, String name, boolean displayOnRemoveDevices,
+ String packageName, String name, boolean displayOnRemoteDevices,
String requiredDisplayCategory) {
ActivityInfo activityInfo = new ActivityInfo();
activityInfo.packageName = packageName;
activityInfo.name = name;
- activityInfo.flags = displayOnRemoveDevices
+ activityInfo.flags = displayOnRemoteDevices
? FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES : FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES;
activityInfo.applicationInfo = mApplicationInfoMock;
activityInfo.requiredDisplayCategory = requiredDisplayCategory;
@@ -1427,7 +1429,7 @@
ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1448,7 +1450,7 @@
ActivityInfo activityInfo = getActivityInfo(
PERMISSION_CONTROLLER_PACKAGE_NAME,
PERMISSION_CONTROLLER_PACKAGE_NAME,
- /* displayOnRemoveDevices */ false,
+ /* displayOnRemoteDevices */ false,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1513,7 +1515,7 @@
ActivityInfo activityInfo = getActivityInfo(
SETTINGS_PACKAGE_NAME,
SETTINGS_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1534,7 +1536,7 @@
ActivityInfo activityInfo = getActivityInfo(
VENDING_PACKAGE_NAME,
VENDING_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1555,7 +1557,7 @@
ActivityInfo activityInfo = getActivityInfo(
GOOGLE_DIALER_PACKAGE_NAME,
GOOGLE_DIALER_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1576,7 +1578,7 @@
ActivityInfo activityInfo = getActivityInfo(
GOOGLE_MAPS_PACKAGE_NAME,
GOOGLE_MAPS_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
activityInfo, mAssociationInfo.getDisplayName());
@@ -1616,6 +1618,54 @@
}
@Test
+ public void canActivityBeLaunched_permissionDialog_flagDisabled_isBlocked() {
+ mSetFlagsRule.disableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ VirtualDeviceParams params = new VirtualDeviceParams.Builder().build();
+ mDeviceImpl.close();
+ mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+ doNothing().when(mContext).startActivityAsUser(any(), any(), any());
+
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
+ DISPLAY_ID_1);
+ ComponentName permissionComponent = getPermissionDialogComponent();
+ ActivityInfo activityInfo = getActivityInfo(
+ permissionComponent.getPackageName(),
+ permissionComponent.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ .isFalse();
+
+ Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent(
+ activityInfo, mAssociationInfo.getDisplayName());
+ verify(mContext).startActivityAsUser(argThat(intent ->
+ intent.filterEquals(blockedAppIntent)), any(), any());
+ }
+
+ @Test
+ public void canActivityBeLaunched_permissionDialog_flagEnabled_isStreamed() {
+ mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS);
+ VirtualDeviceParams params = new VirtualDeviceParams.Builder().build();
+ mDeviceImpl.close();
+ mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params);
+
+ addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
+ GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest(
+ DISPLAY_ID_1);
+ ComponentName permissionComponent = getPermissionDialogComponent();
+ ActivityInfo activityInfo = getActivityInfo(
+ permissionComponent.getPackageName(),
+ permissionComponent.getClassName(),
+ /* displayOnRemoteDevices */ true,
+ /* targetDisplayCategory */ null);
+ assertThat(gwpc.canActivityBeLaunched(activityInfo, null,
+ WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
+ .isTrue();
+ }
+
+ @Test
public void canActivityBeLaunched_activityCanLaunch() {
Intent intent = new Intent(ACTION_VIEW, Uri.parse(TEST_SITE));
addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1);
@@ -1624,7 +1674,7 @@
ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
assertThat(gwpc.canActivityBeLaunched(activityInfo, intent,
WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false))
@@ -1648,7 +1698,7 @@
ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_VIEW);
@@ -1691,7 +1741,7 @@
ActivityInfo activityInfo = getActivityInfo(
NONBLOCKED_APP_PACKAGE_NAME,
NONBLOCKED_APP_PACKAGE_NAME,
- /* displayOnRemoveDevices */ true,
+ /* displayOnRemoteDevices */ true,
/* targetDisplayCategory */ null);
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_VIEW);
@@ -1812,6 +1862,13 @@
NONBLOCKED_APP_PACKAGE_NAME);
}
+ private ComponentName getPermissionDialogComponent() {
+ Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS);
+ PackageManager packageManager = mContext.getPackageManager();
+ intent.setPackage(packageManager.getPermissionControllerPackageName());
+ return intent.resolveActivity(packageManager);
+ }
+
/** Helper class to drop permissions temporarily and restore them at the end of a test. */
static final class DropShellPermissionsTemporarily implements AutoCloseable {
DropShellPermissionsTemporarily() {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
index 90d9452..07dd59d2 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceTest.java
@@ -32,11 +32,12 @@
import android.companion.virtual.flags.Flags;
import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
-import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -51,6 +52,9 @@
private static final String DEVICE_NAME = "VirtualDeviceName";
private static final String DISPLAY_NAME = "DisplayName";
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Mock
private IVirtualDevice mVirtualDevice;
@@ -101,9 +105,10 @@
assertThat(device.getDisplayName().toString()).isEqualTo(DISPLAY_NAME);
}
- @RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
@Test
public void virtualDevice_getDisplayIds() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_VDM_PUBLIC_APIS);
+
VirtualDevice virtualDevice =
new VirtualDevice(
mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);
@@ -116,9 +121,10 @@
assertThat(virtualDevice.getDisplayIds()).isEqualTo(displayIds);
}
- @RequiresFlagsEnabled(Flags.FLAG_VDM_PUBLIC_APIS)
@Test
public void virtualDevice_hasCustomSensorSupport() throws Exception {
+ mSetFlagsRule.enableFlags(Flags.FLAG_VDM_PUBLIC_APIS);
+
VirtualDevice virtualDevice =
new VirtualDevice(
mVirtualDevice, VIRTUAL_DEVICE_ID, /*persistentId=*/null, /*name=*/null);