1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.companion.virtual; 18 19 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM; 20 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT; 21 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS; 22 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_SENSORS; 23 import static android.content.Context.DEVICE_ID_DEFAULT; 24 import static android.content.Context.DEVICE_ID_INVALID; 25 import static android.content.Intent.ACTION_VIEW; 26 import static android.content.pm.ActivityInfo.FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES; 27 import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS; 28 29 import static com.google.common.truth.Truth.assertThat; 30 import static com.google.common.truth.Truth.assertWithMessage; 31 32 import static org.mockito.ArgumentMatchers.any; 33 import static org.mockito.ArgumentMatchers.anyBoolean; 34 import static org.mockito.ArgumentMatchers.anyFloat; 35 import static org.mockito.ArgumentMatchers.anyInt; 36 import static org.mockito.ArgumentMatchers.anyLong; 37 import static org.mockito.ArgumentMatchers.anyString; 38 import static org.mockito.ArgumentMatchers.eq; 39 import static org.mockito.ArgumentMatchers.nullable; 40 import static org.mockito.Mockito.argThat; 41 import static org.mockito.Mockito.clearInvocations; 42 import static org.mockito.Mockito.doAnswer; 43 import static org.mockito.Mockito.doNothing; 44 import static org.mockito.Mockito.doReturn; 45 import static org.mockito.Mockito.mock; 46 import static org.mockito.Mockito.never; 47 import static org.mockito.Mockito.times; 48 import static org.mockito.Mockito.verify; 49 import static org.mockito.Mockito.verifyNoMoreInteractions; 50 import static org.mockito.Mockito.when; 51 import static org.testng.Assert.assertThrows; 52 53 import android.Manifest; 54 import android.app.WindowConfiguration; 55 import android.app.admin.DevicePolicyManager; 56 import android.companion.AssociationInfo; 57 import android.companion.AssociationRequest; 58 import android.companion.virtual.IVirtualDeviceActivityListener; 59 import android.companion.virtual.IVirtualDeviceIntentInterceptor; 60 import android.companion.virtual.IVirtualDeviceSoundEffectListener; 61 import android.companion.virtual.VirtualDeviceManager; 62 import android.companion.virtual.VirtualDeviceParams; 63 import android.companion.virtual.audio.IAudioConfigChangedCallback; 64 import android.companion.virtual.audio.IAudioRoutingCallback; 65 import android.companion.virtual.flags.Flags; 66 import android.companion.virtual.sensor.VirtualSensor; 67 import android.companion.virtual.sensor.VirtualSensorCallback; 68 import android.companion.virtual.sensor.VirtualSensorConfig; 69 import android.content.AttributionSource; 70 import android.content.ComponentName; 71 import android.content.Context; 72 import android.content.ContextWrapper; 73 import android.content.Intent; 74 import android.content.IntentFilter; 75 import android.content.pm.ActivityInfo; 76 import android.content.pm.ApplicationInfo; 77 import android.content.pm.PackageManager; 78 import android.hardware.Sensor; 79 import android.hardware.display.DisplayManagerGlobal; 80 import android.hardware.display.DisplayManagerInternal; 81 import android.hardware.display.IDisplayManager; 82 import android.hardware.display.IVirtualDisplayCallback; 83 import android.hardware.display.VirtualDisplayConfig; 84 import android.hardware.input.IInputManager; 85 import android.hardware.input.VirtualDpadConfig; 86 import android.hardware.input.VirtualKeyEvent; 87 import android.hardware.input.VirtualKeyboardConfig; 88 import android.hardware.input.VirtualMouseButtonEvent; 89 import android.hardware.input.VirtualMouseConfig; 90 import android.hardware.input.VirtualMouseRelativeEvent; 91 import android.hardware.input.VirtualMouseScrollEvent; 92 import android.hardware.input.VirtualNavigationTouchpadConfig; 93 import android.hardware.input.VirtualTouchEvent; 94 import android.hardware.input.VirtualTouchscreenConfig; 95 import android.media.AudioManager; 96 import android.net.MacAddress; 97 import android.net.Uri; 98 import android.os.Binder; 99 import android.os.Handler; 100 import android.os.IBinder; 101 import android.os.IPowerManager; 102 import android.os.IThermalService; 103 import android.os.LocaleList; 104 import android.os.PowerManager; 105 import android.os.Process; 106 import android.os.RemoteException; 107 import android.os.WorkSource; 108 import android.platform.test.annotations.Presubmit; 109 import android.platform.test.flag.junit.SetFlagsRule; 110 import android.testing.AndroidTestingRunner; 111 import android.testing.TestableLooper; 112 import android.util.ArraySet; 113 import android.view.Display; 114 import android.view.DisplayInfo; 115 import android.view.KeyEvent; 116 import android.view.WindowManager; 117 118 import androidx.test.platform.app.InstrumentationRegistry; 119 120 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 121 import com.android.internal.app.BlockedAppStreamingActivity; 122 import com.android.internal.os.BackgroundThread; 123 import com.android.server.LocalServices; 124 import com.android.server.companion.virtual.camera.VirtualCameraController; 125 import com.android.server.input.InputManagerInternal; 126 import com.android.server.sensors.SensorManagerInternal; 127 128 import com.google.android.collect.Sets; 129 130 import org.junit.After; 131 import org.junit.Before; 132 import org.junit.Rule; 133 import org.junit.Test; 134 import org.junit.runner.RunWith; 135 import org.mockito.ArgumentCaptor; 136 import org.mockito.Mock; 137 import org.mockito.Mockito; 138 import org.mockito.MockitoAnnotations; 139 140 import java.util.Arrays; 141 import java.util.Collections; 142 import java.util.List; 143 import java.util.Set; 144 import java.util.function.Consumer; 145 146 @Presubmit 147 @RunWith(AndroidTestingRunner.class) 148 @TestableLooper.RunWithLooper(setAsMainLooper = true) 149 public class VirtualDeviceManagerServiceTest { 150 151 private static final String NONBLOCKED_APP_PACKAGE_NAME = "com.someapp"; 152 private static final String PERMISSION_CONTROLLER_PACKAGE_NAME = 153 "com.android.permissioncontroller"; 154 private static final String SETTINGS_PACKAGE_NAME = "com.android.settings"; 155 private static final String VENDING_PACKAGE_NAME = "com.android.vending"; 156 private static final String GOOGLE_DIALER_PACKAGE_NAME = "com.google.android.dialer"; 157 private static final String GOOGLE_MAPS_PACKAGE_NAME = "com.google.android.apps.maps"; 158 private static final String DEVICE_NAME_1 = "device name 1"; 159 private static final String DEVICE_NAME_2 = "device name 2"; 160 private static final String DEVICE_NAME_3 = "device name 3"; 161 private static final int DISPLAY_ID_1 = 2; 162 private static final int DISPLAY_ID_2 = 3; 163 private static final int NON_EXISTENT_DISPLAY_ID = 42; 164 private static final int DEVICE_OWNER_UID_1 = 50; 165 private static final int DEVICE_OWNER_UID_2 = 51; 166 private static final int UID_1 = 0; 167 private static final int UID_2 = 10; 168 private static final int UID_3 = 10000; 169 private static final int UID_4 = 10001; 170 private static final int PRODUCT_ID = 10; 171 private static final int VENDOR_ID = 5; 172 private static final String UNIQUE_ID = "uniqueid"; 173 private static final String PHYS = "phys"; 174 private static final int INPUT_DEVICE_ID = 53; 175 private static final int HEIGHT = 1800; 176 private static final int WIDTH = 900; 177 private static final int SENSOR_HANDLE = 64; 178 private static final Binder BINDER = new Binder("binder"); 179 private static final int FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES = 0x00000; 180 private static final int VIRTUAL_DEVICE_ID_1 = 42; 181 private static final int VIRTUAL_DEVICE_ID_2 = 43; 182 private static final VirtualDisplayConfig VIRTUAL_DISPLAY_CONFIG = 183 new VirtualDisplayConfig.Builder("virtual_display", 640, 480, 400).build(); 184 private static final VirtualDpadConfig DPAD_CONFIG = 185 new VirtualDpadConfig.Builder() 186 .setVendorId(VENDOR_ID) 187 .setProductId(PRODUCT_ID) 188 .setInputDeviceName(DEVICE_NAME_1) 189 .setAssociatedDisplayId(DISPLAY_ID_1) 190 .build(); 191 private static final VirtualKeyboardConfig KEYBOARD_CONFIG = 192 new VirtualKeyboardConfig.Builder() 193 .setVendorId(VENDOR_ID) 194 .setProductId(PRODUCT_ID) 195 .setInputDeviceName(DEVICE_NAME_1) 196 .setAssociatedDisplayId(DISPLAY_ID_1) 197 .setLanguageTag(VirtualKeyboardConfig.DEFAULT_LANGUAGE_TAG) 198 .setLayoutType(VirtualKeyboardConfig.DEFAULT_LAYOUT_TYPE) 199 .build(); 200 private static final VirtualMouseConfig MOUSE_CONFIG = 201 new VirtualMouseConfig.Builder() 202 .setVendorId(VENDOR_ID) 203 .setProductId(PRODUCT_ID) 204 .setInputDeviceName(DEVICE_NAME_1) 205 .setAssociatedDisplayId(DISPLAY_ID_1) 206 .build(); 207 private static final VirtualTouchscreenConfig TOUCHSCREEN_CONFIG = 208 new VirtualTouchscreenConfig.Builder(WIDTH, HEIGHT) 209 .setVendorId(VENDOR_ID) 210 .setProductId(PRODUCT_ID) 211 .setInputDeviceName(DEVICE_NAME_1) 212 .setAssociatedDisplayId(DISPLAY_ID_1) 213 .build(); 214 private static final VirtualNavigationTouchpadConfig NAVIGATION_TOUCHPAD_CONFIG = 215 new VirtualNavigationTouchpadConfig.Builder(WIDTH, HEIGHT) 216 .setVendorId(VENDOR_ID) 217 .setProductId(PRODUCT_ID) 218 .setInputDeviceName(DEVICE_NAME_1) 219 .setAssociatedDisplayId(DISPLAY_ID_1) 220 .build(); 221 private static final String TEST_SITE = "http://test"; 222 223 @Rule 224 public SetFlagsRule mSetFlagsRule = new SetFlagsRule(); 225 226 @Rule 227 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 228 InstrumentationRegistry.getInstrumentation().getUiAutomation(), 229 Manifest.permission.CREATE_VIRTUAL_DEVICE); 230 231 private Context mContext; 232 private InputManagerMockHelper mInputManagerMockHelper; 233 private VirtualDeviceImpl mDeviceImpl; 234 private InputController mInputController; 235 private SensorController mSensorController; 236 private CameraAccessController mCameraAccessController; 237 private AssociationInfo mAssociationInfo; 238 private VirtualDeviceManagerService mVdms; 239 private VirtualDeviceManagerInternal mLocalService; 240 private VirtualDeviceManagerService.VirtualDeviceManagerImpl mVdm; 241 private VirtualDeviceManagerService.VirtualDeviceManagerNativeImpl mVdmNative; 242 private VirtualDeviceLog mVirtualDeviceLog; 243 @Mock 244 private InputController.NativeWrapper mNativeWrapperMock; 245 @Mock 246 private DisplayManagerInternal mDisplayManagerInternalMock; 247 @Mock 248 private IDisplayManager mIDisplayManager; 249 @Mock 250 private VirtualDeviceImpl.PendingTrampolineCallback mPendingTrampolineCallback; 251 @Mock 252 private DevicePolicyManager mDevicePolicyManagerMock; 253 @Mock 254 private InputManagerInternal mInputManagerInternalMock; 255 @Mock 256 private SensorManagerInternal mSensorManagerInternalMock; 257 @Mock 258 private VirtualSensorCallback mSensorCallback; 259 @Mock 260 private IVirtualDeviceActivityListener mActivityListener; 261 @Mock 262 private IVirtualDeviceSoundEffectListener mSoundEffectListener; 263 @Mock 264 private IVirtualDisplayCallback mVirtualDisplayCallback; 265 @Mock 266 private Consumer<ArraySet<Integer>> mRunningAppsChangedCallback; 267 @Mock 268 private VirtualDeviceManagerInternal.AppsOnVirtualDeviceListener mAppsOnVirtualDeviceListener; 269 @Mock 270 private Consumer<String> mPersistentDeviceIdRemovedListener; 271 @Mock 272 IPowerManager mIPowerManagerMock; 273 @Mock 274 IThermalService mIThermalServiceMock; 275 @Mock 276 private IAudioRoutingCallback mRoutingCallback; 277 @Mock 278 private IAudioConfigChangedCallback mConfigChangedCallback; 279 @Mock 280 private CameraAccessController.CameraAccessBlockedCallback mCameraAccessBlockedCallback; 281 @Mock 282 private ApplicationInfo mApplicationInfoMock; 283 @Mock 284 IInputManager mIInputManagerMock; 285 getBlockedActivities()286 private ArraySet<ComponentName> getBlockedActivities() { 287 ArraySet<ComponentName> blockedActivities = new ArraySet<>(); 288 blockedActivities.add(new ComponentName(SETTINGS_PACKAGE_NAME, SETTINGS_PACKAGE_NAME)); 289 blockedActivities.add(new ComponentName(VENDING_PACKAGE_NAME, VENDING_PACKAGE_NAME)); 290 blockedActivities.add( 291 new ComponentName(GOOGLE_DIALER_PACKAGE_NAME, GOOGLE_DIALER_PACKAGE_NAME)); 292 blockedActivities.add( 293 new ComponentName(GOOGLE_MAPS_PACKAGE_NAME, GOOGLE_MAPS_PACKAGE_NAME)); 294 return blockedActivities; 295 } 296 createRestrictedActivityBlockedIntent(Set<String> displayCategories, String targetDisplayCategory)297 private Intent createRestrictedActivityBlockedIntent(Set<String> displayCategories, 298 String targetDisplayCategory) { 299 when(mDisplayManagerInternalMock.createVirtualDisplay(any(), any(), any(), any(), 300 eq(NONBLOCKED_APP_PACKAGE_NAME))).thenReturn(DISPLAY_ID_1); 301 VirtualDisplayConfig config = new VirtualDisplayConfig.Builder("display", 640, 480, 302 420).setDisplayCategories(displayCategories).build(); 303 mDeviceImpl.createVirtualDisplay(config, mVirtualDisplayCallback, 304 NONBLOCKED_APP_PACKAGE_NAME); 305 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 306 DISPLAY_ID_1); 307 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 308 309 ActivityInfo activityInfo = getActivityInfo( 310 NONBLOCKED_APP_PACKAGE_NAME, 311 NONBLOCKED_APP_PACKAGE_NAME, 312 /* displayOnRemoteDevices= */ true, 313 targetDisplayCategory); 314 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 315 activityInfo, mAssociationInfo.getDisplayName()); 316 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 317 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 318 return blockedAppIntent; 319 } 320 321 getActivityInfo( String packageName, String name, boolean displayOnRemoteDevices, String requiredDisplayCategory)322 private ActivityInfo getActivityInfo( 323 String packageName, String name, boolean displayOnRemoteDevices, 324 String requiredDisplayCategory) { 325 ActivityInfo activityInfo = new ActivityInfo(); 326 activityInfo.packageName = packageName; 327 activityInfo.name = name; 328 activityInfo.flags = displayOnRemoteDevices 329 ? FLAG_CAN_DISPLAY_ON_REMOTE_DEVICES : FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES; 330 activityInfo.applicationInfo = mApplicationInfoMock; 331 activityInfo.requiredDisplayCategory = requiredDisplayCategory; 332 return activityInfo; 333 } 334 335 @Before setUp()336 public void setUp() throws Exception { 337 MockitoAnnotations.initMocks(this); 338 339 LocalServices.removeServiceForTest(DisplayManagerInternal.class); 340 LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); 341 342 doNothing().when(mInputManagerInternalMock) 343 .setMousePointerAccelerationEnabled(anyBoolean(), anyInt()); 344 doNothing().when(mInputManagerInternalMock).setPointerIconVisible(anyBoolean(), anyInt()); 345 LocalServices.removeServiceForTest(InputManagerInternal.class); 346 LocalServices.addService(InputManagerInternal.class, mInputManagerInternalMock); 347 348 LocalServices.removeServiceForTest(SensorManagerInternal.class); 349 LocalServices.addService(SensorManagerInternal.class, mSensorManagerInternalMock); 350 351 final DisplayInfo displayInfo = new DisplayInfo(); 352 displayInfo.uniqueId = UNIQUE_ID; 353 doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt()); 354 doReturn(Display.INVALID_DISPLAY).when(mDisplayManagerInternalMock) 355 .getDisplayIdToMirror(anyInt()); 356 LocalServices.removeServiceForTest(DisplayManagerInternal.class); 357 LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); 358 359 mContext = Mockito.spy(new ContextWrapper( 360 InstrumentationRegistry.getInstrumentation().getTargetContext())); 361 doReturn(mContext).when(mContext).createContextAsUser(eq(Process.myUserHandle()), anyInt()); 362 doNothing().when(mContext).sendBroadcastAsUser(any(), any()); 363 when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE)).thenReturn( 364 mDevicePolicyManagerMock); 365 366 PowerManager powerManager = new PowerManager(mContext, mIPowerManagerMock, 367 mIThermalServiceMock, 368 new Handler(TestableLooper.get(this).getLooper())); 369 when(mContext.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager); 370 371 when(mNativeWrapperMock.writeButtonEvent(anyLong(), anyInt(), anyInt(), anyLong())) 372 .thenReturn(true); 373 when(mNativeWrapperMock.writeRelativeEvent(anyLong(), anyFloat(), anyFloat(), anyLong())) 374 .thenReturn(true); 375 when(mNativeWrapperMock.writeScrollEvent(anyLong(), anyFloat(), anyFloat(), anyLong())) 376 .thenReturn(true); 377 when(mNativeWrapperMock.writeKeyEvent(anyLong(), anyInt(), anyInt(), anyLong())) 378 .thenReturn(true); 379 when(mNativeWrapperMock.writeTouchEvent(anyLong(), anyInt(), anyInt(), anyInt(), 380 anyFloat(), anyFloat(), anyFloat(), anyFloat(), anyLong())) 381 .thenReturn(true); 382 383 mInputManagerMockHelper = new InputManagerMockHelper( 384 TestableLooper.get(this), mNativeWrapperMock, mIInputManagerMock); 385 // Allow virtual devices to be created on the looper thread for testing. 386 final InputController.DeviceCreationThreadVerifier threadVerifier = () -> true; 387 mInputController = new InputController(mNativeWrapperMock, 388 new Handler(TestableLooper.get(this).getLooper()), 389 mContext.getSystemService(WindowManager.class), 390 AttributionSource.myAttributionSource(), threadVerifier); 391 mCameraAccessController = 392 new CameraAccessController(mContext, mLocalService, mCameraAccessBlockedCallback); 393 394 mAssociationInfo = createAssociationInfo( 395 /* associationId= */ 1, AssociationRequest.DEVICE_PROFILE_APP_STREAMING); 396 397 mVdms = new VirtualDeviceManagerService(mContext); 398 mLocalService = mVdms.getLocalServiceInstance(); 399 mVdm = mVdms.new VirtualDeviceManagerImpl(); 400 mVdmNative = mVdms.new VirtualDeviceManagerNativeImpl(); 401 mVirtualDeviceLog = new VirtualDeviceLog(mContext); 402 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1); 403 mSensorController = mDeviceImpl.getSensorControllerForTest(); 404 } 405 406 @After tearDown()407 public void tearDown() { 408 mDeviceImpl.close(); 409 mInputManagerMockHelper.tearDown(); 410 } 411 412 @Test getDeviceIdForDisplayId_invalidDisplayId_returnsDefault()413 public void getDeviceIdForDisplayId_invalidDisplayId_returnsDefault() { 414 assertThat(mVdm.getDeviceIdForDisplayId(Display.INVALID_DISPLAY)) 415 .isEqualTo(DEVICE_ID_DEFAULT); 416 assertThat(mLocalService.getDeviceIdForDisplayId(Display.INVALID_DISPLAY)) 417 .isEqualTo(DEVICE_ID_DEFAULT); 418 } 419 420 @Test getDeviceIdForDisplayId_defaultDisplayId_returnsDefault()421 public void getDeviceIdForDisplayId_defaultDisplayId_returnsDefault() { 422 assertThat(mVdm.getDeviceIdForDisplayId(Display.DEFAULT_DISPLAY)) 423 .isEqualTo(DEVICE_ID_DEFAULT); 424 assertThat(mLocalService.getDeviceIdForDisplayId(Display.DEFAULT_DISPLAY)) 425 .isEqualTo(DEVICE_ID_DEFAULT); 426 } 427 428 @Test getDeviceIdForDisplayId_nonExistentDisplayId_returnsDefault()429 public void getDeviceIdForDisplayId_nonExistentDisplayId_returnsDefault() { 430 assertThat(mVdm.getDeviceIdForDisplayId(NON_EXISTENT_DISPLAY_ID)) 431 .isEqualTo(DEVICE_ID_DEFAULT); 432 assertThat(mLocalService.getDeviceIdForDisplayId(NON_EXISTENT_DISPLAY_ID)) 433 .isEqualTo(DEVICE_ID_DEFAULT); 434 } 435 436 @Test getDeviceIdForDisplayId_withValidVirtualDisplayId_returnsDeviceId()437 public void getDeviceIdForDisplayId_withValidVirtualDisplayId_returnsDeviceId() { 438 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 439 440 assertThat(mVdm.getDeviceIdForDisplayId(DISPLAY_ID_1)) 441 .isEqualTo(mDeviceImpl.getDeviceId()); 442 assertThat(mLocalService.getDeviceIdForDisplayId(DISPLAY_ID_1)) 443 .isEqualTo(mDeviceImpl.getDeviceId()); 444 } 445 446 @Test isDeviceIdValid_invalidDeviceId_returnsFalse()447 public void isDeviceIdValid_invalidDeviceId_returnsFalse() { 448 assertThat(mVdm.isValidVirtualDeviceId(DEVICE_ID_INVALID)).isFalse(); 449 assertThat(mLocalService.isValidVirtualDeviceId(DEVICE_ID_INVALID)).isFalse(); 450 } 451 452 @Test isDeviceIdValid_defaultDeviceId_returnsFalse()453 public void isDeviceIdValid_defaultDeviceId_returnsFalse() { 454 assertThat(mVdm.isValidVirtualDeviceId(DEVICE_ID_DEFAULT)).isFalse(); 455 assertThat(mLocalService.isValidVirtualDeviceId(DEVICE_ID_DEFAULT)).isFalse(); 456 } 457 458 @Test isDeviceIdValid_validVirtualDeviceId_returnsTrue()459 public void isDeviceIdValid_validVirtualDeviceId_returnsTrue() { 460 assertThat(mVdm.isValidVirtualDeviceId(mDeviceImpl.getDeviceId())).isTrue(); 461 assertThat(mLocalService.isValidVirtualDeviceId(mDeviceImpl.getDeviceId())).isTrue(); 462 } 463 464 @Test isDeviceIdValid_nonExistentDeviceId_returnsFalse()465 public void isDeviceIdValid_nonExistentDeviceId_returnsFalse() { 466 assertThat(mVdm.isValidVirtualDeviceId(mDeviceImpl.getDeviceId() + 1)).isFalse(); 467 assertThat(mLocalService.isValidVirtualDeviceId(mDeviceImpl.getDeviceId() + 1)).isFalse(); 468 } 469 470 @Test getDevicePolicy_invalidDeviceId_returnsDefault()471 public void getDevicePolicy_invalidDeviceId_returnsDefault() { 472 assertThat(mVdm.getDevicePolicy(DEVICE_ID_INVALID, POLICY_TYPE_SENSORS)) 473 .isEqualTo(DEVICE_POLICY_DEFAULT); 474 assertThat(mVdmNative.getDevicePolicy(DEVICE_ID_INVALID, POLICY_TYPE_SENSORS)) 475 .isEqualTo(DEVICE_POLICY_DEFAULT); 476 } 477 478 @Test getDevicePolicy_defaultDeviceId_returnsDefault()479 public void getDevicePolicy_defaultDeviceId_returnsDefault() { 480 assertThat(mVdm.getDevicePolicy(DEVICE_ID_DEFAULT, POLICY_TYPE_SENSORS)) 481 .isEqualTo(DEVICE_POLICY_DEFAULT); 482 assertThat(mVdmNative.getDevicePolicy(DEVICE_ID_DEFAULT, POLICY_TYPE_SENSORS)) 483 .isEqualTo(DEVICE_POLICY_DEFAULT); 484 } 485 486 @Test getDevicePolicy_nonExistentDeviceId_returnsDefault()487 public void getDevicePolicy_nonExistentDeviceId_returnsDefault() { 488 assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId() + 1, POLICY_TYPE_SENSORS)) 489 .isEqualTo(DEVICE_POLICY_DEFAULT); 490 assertThat(mVdmNative.getDevicePolicy(mDeviceImpl.getDeviceId() + 1, POLICY_TYPE_SENSORS)) 491 .isEqualTo(DEVICE_POLICY_DEFAULT); 492 } 493 494 @Test getDevicePolicy_unspecifiedPolicy_returnsDefault()495 public void getDevicePolicy_unspecifiedPolicy_returnsDefault() { 496 assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS)) 497 .isEqualTo(DEVICE_POLICY_DEFAULT); 498 assertThat(mVdmNative.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS)) 499 .isEqualTo(DEVICE_POLICY_DEFAULT); 500 } 501 502 @Test getDevicePolicy_returnsCustom()503 public void getDevicePolicy_returnsCustom() { 504 VirtualDeviceParams params = new VirtualDeviceParams 505 .Builder() 506 .setBlockedActivities(getBlockedActivities()) 507 .setDevicePolicy(POLICY_TYPE_SENSORS, DEVICE_POLICY_CUSTOM) 508 .build(); 509 mDeviceImpl.close(); 510 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params); 511 512 assertThat(mVdm.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS)) 513 .isEqualTo(DEVICE_POLICY_CUSTOM); 514 assertThat(mVdmNative.getDevicePolicy(mDeviceImpl.getDeviceId(), POLICY_TYPE_SENSORS)) 515 .isEqualTo(DEVICE_POLICY_CUSTOM); 516 } 517 518 @Test getDevicePolicy_defaultRecentsPolicy_gwpcCanShowRecentsOnHostDevice()519 public void getDevicePolicy_defaultRecentsPolicy_gwpcCanShowRecentsOnHostDevice() { 520 VirtualDeviceParams params = new VirtualDeviceParams 521 .Builder() 522 .build(); 523 mDeviceImpl.close(); 524 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params); 525 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 526 527 GenericWindowPolicyController gwpc = 528 mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1); 529 assertThat(gwpc.canShowTasksInHostDeviceRecents()).isTrue(); 530 } 531 532 @Test getDevicePolicy_customRecentsPolicy_gwpcCannotShowRecentsOnHostDevice()533 public void getDevicePolicy_customRecentsPolicy_gwpcCannotShowRecentsOnHostDevice() { 534 VirtualDeviceParams params = new VirtualDeviceParams 535 .Builder() 536 .setDevicePolicy(POLICY_TYPE_RECENTS, DEVICE_POLICY_CUSTOM) 537 .build(); 538 mDeviceImpl.close(); 539 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params); 540 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 541 542 GenericWindowPolicyController gwpc = 543 mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1); 544 assertThat(gwpc.canShowTasksInHostDeviceRecents()).isFalse(); 545 } 546 547 @Test getDeviceOwnerUid_oneDevice_returnsCorrectId()548 public void getDeviceOwnerUid_oneDevice_returnsCorrectId() { 549 int ownerUid = mLocalService.getDeviceOwnerUid(mDeviceImpl.getDeviceId()); 550 assertThat(ownerUid).isEqualTo(mDeviceImpl.getOwnerUid()); 551 } 552 553 @Test getDeviceOwnerUid_twoDevices_returnsCorrectId()554 public void getDeviceOwnerUid_twoDevices_returnsCorrectId() { 555 createVirtualDevice(VIRTUAL_DEVICE_ID_2, DEVICE_OWNER_UID_2); 556 557 int secondDeviceOwner = mLocalService.getDeviceOwnerUid(VIRTUAL_DEVICE_ID_2); 558 assertThat(secondDeviceOwner).isEqualTo(DEVICE_OWNER_UID_2); 559 560 int firstDeviceOwner = mLocalService.getDeviceOwnerUid(VIRTUAL_DEVICE_ID_1); 561 assertThat(firstDeviceOwner).isEqualTo(DEVICE_OWNER_UID_1); 562 } 563 564 @Test getDeviceOwnerUid_nonExistentDevice_returnsInvalidUid()565 public void getDeviceOwnerUid_nonExistentDevice_returnsInvalidUid() { 566 int nonExistentDeviceId = DEVICE_ID_DEFAULT; 567 int ownerUid = mLocalService.getDeviceOwnerUid(nonExistentDeviceId); 568 assertThat(ownerUid).isEqualTo(Process.INVALID_UID); 569 } 570 571 @Test getVirtualSensor_defaultDeviceId_returnsNull()572 public void getVirtualSensor_defaultDeviceId_returnsNull() { 573 assertThat(mLocalService.getVirtualSensor(DEVICE_ID_DEFAULT, SENSOR_HANDLE)).isNull(); 574 } 575 576 @Test getVirtualSensor_invalidDeviceId_returnsNull()577 public void getVirtualSensor_invalidDeviceId_returnsNull() { 578 assertThat(mLocalService.getVirtualSensor(DEVICE_ID_INVALID, SENSOR_HANDLE)).isNull(); 579 } 580 581 @Test getVirtualSensor_noSensors_returnsNull()582 public void getVirtualSensor_noSensors_returnsNull() { 583 assertThat(mLocalService.getVirtualSensor(VIRTUAL_DEVICE_ID_1, SENSOR_HANDLE)).isNull(); 584 } 585 586 @Test getVirtualSensor_returnsCorrectSensor()587 public void getVirtualSensor_returnsCorrectSensor() { 588 VirtualDeviceParams params = new VirtualDeviceParams.Builder() 589 .setDevicePolicy(POLICY_TYPE_SENSORS, DEVICE_POLICY_CUSTOM) 590 .addVirtualSensorConfig( 591 new VirtualSensorConfig.Builder(Sensor.TYPE_ACCELEROMETER, DEVICE_NAME_1) 592 .build()) 593 .setVirtualSensorCallback(BackgroundThread.getExecutor(), mSensorCallback) 594 .build(); 595 596 doReturn(SENSOR_HANDLE).when(mSensorManagerInternalMock).createRuntimeSensor( 597 anyInt(), anyInt(), anyString(), anyString(), anyFloat(), anyFloat(), anyFloat(), 598 anyInt(), anyInt(), anyInt(), any()); 599 mDeviceImpl.close(); 600 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params); 601 602 VirtualSensor sensor = mLocalService.getVirtualSensor(VIRTUAL_DEVICE_ID_1, SENSOR_HANDLE); 603 assertThat(sensor).isNotNull(); 604 assertThat(sensor.getDeviceId()).isEqualTo(VIRTUAL_DEVICE_ID_1); 605 assertThat(sensor.getHandle()).isEqualTo(SENSOR_HANDLE); 606 assertThat(sensor.getType()).isEqualTo(Sensor.TYPE_ACCELEROMETER); 607 } 608 609 @Test testIsInputDeviceOwnedByVirtualDevice()610 public void testIsInputDeviceOwnedByVirtualDevice() { 611 assertThat(mLocalService.isInputDeviceOwnedByVirtualDevice(INPUT_DEVICE_ID)).isFalse(); 612 613 final int fd = 1; 614 mInputController.addDeviceForTesting(BINDER, fd, 615 InputController.InputDeviceDescriptor.TYPE_KEYBOARD, DISPLAY_ID_1, PHYS, 616 DEVICE_NAME_1, INPUT_DEVICE_ID); 617 assertThat(mLocalService.isInputDeviceOwnedByVirtualDevice(INPUT_DEVICE_ID)).isTrue(); 618 619 mInputController.unregisterInputDevice(BINDER); 620 assertThat(mLocalService.isInputDeviceOwnedByVirtualDevice(INPUT_DEVICE_ID)).isFalse(); 621 } 622 623 @Test getDeviceIdsForUid_noRunningApps_returnsNull()624 public void getDeviceIdsForUid_noRunningApps_returnsNull() { 625 assertThat(mLocalService.getDeviceIdsForUid(UID_1)).isEmpty(); 626 assertThat(mVdmNative.getDeviceIdsForUid(UID_1)).isEmpty(); 627 } 628 629 @Test getDeviceIdsForUid_differentUidOnDevice_returnsNull()630 public void getDeviceIdsForUid_differentUidOnDevice_returnsNull() { 631 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 632 mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged( 633 Sets.newArraySet(UID_2)); 634 635 assertThat(mLocalService.getDeviceIdsForUid(UID_1)).isEmpty(); 636 assertThat(mVdmNative.getDeviceIdsForUid(UID_1)).isEmpty(); 637 } 638 639 @Test getDeviceIdsForUid_oneUidOnDevice_returnsCorrectId()640 public void getDeviceIdsForUid_oneUidOnDevice_returnsCorrectId() { 641 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 642 mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged( 643 Sets.newArraySet(UID_1)); 644 645 int deviceId = mDeviceImpl.getDeviceId(); 646 assertThat(mLocalService.getDeviceIdsForUid(UID_1)).containsExactly(deviceId); 647 assertThat(mVdmNative.getDeviceIdsForUid(UID_1)).asList().containsExactly(deviceId); 648 } 649 650 @Test getDeviceIdsForUid_twoUidsOnDevice_returnsCorrectId()651 public void getDeviceIdsForUid_twoUidsOnDevice_returnsCorrectId() { 652 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 653 654 mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged( 655 Sets.newArraySet(UID_1, UID_2)); 656 657 int deviceId = mDeviceImpl.getDeviceId(); 658 assertThat(mLocalService.getDeviceIdsForUid(UID_1)).containsExactly(deviceId); 659 assertThat(mVdmNative.getDeviceIdsForUid(UID_1)).asList().containsExactly(deviceId); 660 } 661 662 @Test getDeviceIdsForUid_twoDevicesUidOnOne_returnsCorrectId()663 public void getDeviceIdsForUid_twoDevicesUidOnOne_returnsCorrectId() { 664 VirtualDeviceImpl secondDevice = createVirtualDevice(VIRTUAL_DEVICE_ID_2, 665 DEVICE_OWNER_UID_2); 666 addVirtualDisplay(secondDevice, DISPLAY_ID_2); 667 668 secondDevice.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_2).onRunningAppsChanged( 669 Sets.newArraySet(UID_1)); 670 671 int deviceId = secondDevice.getDeviceId(); 672 assertThat(mLocalService.getDeviceIdsForUid(UID_1)).containsExactly(deviceId); 673 assertThat(mVdmNative.getDeviceIdsForUid(UID_1)).asList().containsExactly(deviceId); 674 } 675 676 @Test getDeviceIdsForUid_twoDevicesUidOnBoth_returnsCorrectId()677 public void getDeviceIdsForUid_twoDevicesUidOnBoth_returnsCorrectId() { 678 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 679 VirtualDeviceImpl secondDevice = createVirtualDevice(VIRTUAL_DEVICE_ID_2, 680 DEVICE_OWNER_UID_2); 681 addVirtualDisplay(secondDevice, DISPLAY_ID_2); 682 683 684 mDeviceImpl.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_1).onRunningAppsChanged( 685 Sets.newArraySet(UID_1)); 686 secondDevice.getDisplayWindowPolicyControllerForTest(DISPLAY_ID_2).onRunningAppsChanged( 687 Sets.newArraySet(UID_1, UID_2)); 688 689 assertThat(mLocalService.getDeviceIdsForUid(UID_1)).containsExactly( 690 mDeviceImpl.getDeviceId(), secondDevice.getDeviceId()); 691 assertThat(mVdmNative.getDeviceIdsForUid(UID_1)).asList().containsExactly( 692 mDeviceImpl.getDeviceId(), secondDevice.getDeviceId()); 693 } 694 695 @Test getPreferredLocaleListForApp_keyboardAttached_returnLocaleHints()696 public void getPreferredLocaleListForApp_keyboardAttached_returnLocaleHints() { 697 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 698 mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER); 699 700 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), Sets.newArraySet(UID_1)); 701 702 LocaleList localeList = mLocalService.getPreferredLocaleListForUid(UID_1); 703 assertThat(localeList).isEqualTo( 704 LocaleList.forLanguageTags(KEYBOARD_CONFIG.getLanguageTag())); 705 } 706 707 @Test getPreferredLocaleListForApp_noKeyboardAttached_nullLocaleHints()708 public void getPreferredLocaleListForApp_noKeyboardAttached_nullLocaleHints() { 709 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), Sets.newArraySet(UID_1)); 710 711 // no preceding call to createVirtualKeyboard() 712 assertThat(mLocalService.getPreferredLocaleListForUid(UID_1)).isNull(); 713 } 714 715 @Test getPreferredLocaleListForApp_appOnMultipleVD_localeOnFirstVDReturned()716 public void getPreferredLocaleListForApp_appOnMultipleVD_localeOnFirstVDReturned() { 717 VirtualDeviceImpl secondDevice = createVirtualDevice(VIRTUAL_DEVICE_ID_2, 718 DEVICE_OWNER_UID_2); 719 Binder secondBinder = new Binder("secondBinder"); 720 VirtualKeyboardConfig firstKeyboardConfig = 721 new VirtualKeyboardConfig.Builder() 722 .setVendorId(VENDOR_ID) 723 .setProductId(PRODUCT_ID) 724 .setInputDeviceName(DEVICE_NAME_1) 725 .setAssociatedDisplayId(DISPLAY_ID_1) 726 .setLanguageTag("zh-CN") 727 .build(); 728 VirtualKeyboardConfig secondKeyboardConfig = 729 new VirtualKeyboardConfig.Builder() 730 .setVendorId(VENDOR_ID) 731 .setProductId(PRODUCT_ID) 732 .setInputDeviceName(DEVICE_NAME_2) 733 .setAssociatedDisplayId(DISPLAY_ID_2) 734 .setLanguageTag("fr-FR") 735 .build(); 736 737 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 738 addVirtualDisplay(secondDevice, DISPLAY_ID_2); 739 740 mDeviceImpl.createVirtualKeyboard(firstKeyboardConfig, BINDER); 741 secondDevice.createVirtualKeyboard(secondKeyboardConfig, secondBinder); 742 743 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), Sets.newArraySet(UID_1)); 744 mVdms.notifyRunningAppsChanged(secondDevice.getDeviceId(), Sets.newArraySet(UID_1)); 745 746 LocaleList localeList = mLocalService.getPreferredLocaleListForUid(UID_1); 747 assertThat(localeList).isEqualTo( 748 LocaleList.forLanguageTags(firstKeyboardConfig.getLanguageTag())); 749 } 750 751 @Test cameraAccessController_observerCountUpdated()752 public void cameraAccessController_observerCountUpdated() { 753 assertThat(mCameraAccessController.getObserverCount()).isEqualTo(1); 754 755 VirtualDeviceImpl secondDevice = 756 createVirtualDevice(VIRTUAL_DEVICE_ID_2, DEVICE_OWNER_UID_2); 757 assertThat(mCameraAccessController.getObserverCount()).isEqualTo(2); 758 759 mDeviceImpl.close(); 760 assertThat(mCameraAccessController.getObserverCount()).isEqualTo(1); 761 762 secondDevice.close(); 763 assertThat(mCameraAccessController.getObserverCount()).isEqualTo(0); 764 } 765 766 @Test onVirtualDisplayRemovedLocked_doesNotThrowException()767 public void onVirtualDisplayRemovedLocked_doesNotThrowException() { 768 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 769 // This call should not throw any exceptions. 770 mDeviceImpl.onVirtualDisplayRemoved(DISPLAY_ID_1); 771 } 772 773 @Test onPersistentDeviceIdsRemoved_listenersNotified()774 public void onPersistentDeviceIdsRemoved_listenersNotified() { 775 mLocalService.registerPersistentDeviceIdRemovedListener(mPersistentDeviceIdRemovedListener); 776 mLocalService.onPersistentDeviceIdsRemoved(Set.of(mDeviceImpl.getPersistentDeviceId())); 777 TestableLooper.get(this).processAllMessages(); 778 779 verify(mPersistentDeviceIdRemovedListener).accept(mDeviceImpl.getPersistentDeviceId()); 780 } 781 782 @Test onCdmAssociationsChanged_persistentDeviceIdRemovedListenersNotified()783 public void onCdmAssociationsChanged_persistentDeviceIdRemovedListenersNotified() { 784 mLocalService.registerPersistentDeviceIdRemovedListener(mPersistentDeviceIdRemovedListener); 785 mVdms.onCdmAssociationsChanged(List.of(mAssociationInfo)); 786 TestableLooper.get(this).processAllMessages(); 787 788 mVdms.onCdmAssociationsChanged(List.of( 789 createAssociationInfo(2, AssociationRequest.DEVICE_PROFILE_APP_STREAMING), 790 createAssociationInfo(3, AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION), 791 createAssociationInfo(4, AssociationRequest.DEVICE_PROFILE_WATCH))); 792 TestableLooper.get(this).processAllMessages(); 793 794 verify(mPersistentDeviceIdRemovedListener).accept(mDeviceImpl.getPersistentDeviceId()); 795 796 mVdms.onCdmAssociationsChanged(Collections.emptyList()); 797 TestableLooper.get(this).processAllMessages(); 798 799 verify(mPersistentDeviceIdRemovedListener) 800 .accept(VirtualDeviceImpl.createPersistentDeviceId(2)); 801 verify(mPersistentDeviceIdRemovedListener) 802 .accept(VirtualDeviceImpl.createPersistentDeviceId(3)); 803 verifyNoMoreInteractions(mPersistentDeviceIdRemovedListener); 804 } 805 806 @Test getAllPersistentDeviceIds_respectsCurrentAssociations()807 public void getAllPersistentDeviceIds_respectsCurrentAssociations() { 808 mVdms.onCdmAssociationsChanged(List.of(mAssociationInfo)); 809 TestableLooper.get(this).processAllMessages(); 810 811 assertThat(mLocalService.getAllPersistentDeviceIds()) 812 .containsExactly(mDeviceImpl.getPersistentDeviceId()); 813 814 mVdms.onCdmAssociationsChanged(List.of( 815 createAssociationInfo(2, AssociationRequest.DEVICE_PROFILE_APP_STREAMING), 816 createAssociationInfo(3, AssociationRequest.DEVICE_PROFILE_AUTOMOTIVE_PROJECTION), 817 createAssociationInfo(4, AssociationRequest.DEVICE_PROFILE_WATCH))); 818 TestableLooper.get(this).processAllMessages(); 819 820 assertThat(mLocalService.getAllPersistentDeviceIds()).containsExactly( 821 VirtualDeviceImpl.createPersistentDeviceId(2), 822 VirtualDeviceImpl.createPersistentDeviceId(3)); 823 824 mVdms.onCdmAssociationsChanged(Collections.emptyList()); 825 TestableLooper.get(this).processAllMessages(); 826 827 assertThat(mLocalService.getAllPersistentDeviceIds()).isEmpty(); 828 } 829 830 @Test getDisplayNameForPersistentDeviceId_nonExistentPeristentId_returnsNull()831 public void getDisplayNameForPersistentDeviceId_nonExistentPeristentId_returnsNull() { 832 assertThat(mVdm.getDisplayNameForPersistentDeviceId("nonExistentPersistentId")).isNull(); 833 } 834 835 @Test getDisplayNameForPersistentDeviceId_defaultDevicePeristentId_returnsNull()836 public void getDisplayNameForPersistentDeviceId_defaultDevicePeristentId_returnsNull() { 837 assertThat(mVdm.getDisplayNameForPersistentDeviceId( 838 VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT)) 839 .isNull(); 840 } 841 842 @Test getDisplayNameForPersistentDeviceId_validVirtualDevice_returnsCorrectId()843 public void getDisplayNameForPersistentDeviceId_validVirtualDevice_returnsCorrectId() { 844 mVdms.onCdmAssociationsChanged(List.of(mAssociationInfo)); 845 CharSequence persistentIdDisplayName = 846 mVdm.getDisplayNameForPersistentDeviceId(mDeviceImpl.getPersistentDeviceId()); 847 assertThat(persistentIdDisplayName.toString()) 848 .isEqualTo(mAssociationInfo.getDisplayName().toString()); 849 } 850 851 @Test getDisplayNameForPersistentDeviceId_noVirtualDevice_returnsCorrectId()852 public void getDisplayNameForPersistentDeviceId_noVirtualDevice_returnsCorrectId() { 853 CharSequence displayName = "New display name for the new association"; 854 mVdms.onCdmAssociationsChanged(List.of( 855 createAssociationInfo(2, AssociationRequest.DEVICE_PROFILE_APP_STREAMING, 856 displayName))); 857 858 CharSequence persistentIdDisplayName = 859 mVdm.getDisplayNameForPersistentDeviceId( 860 VirtualDeviceImpl.createPersistentDeviceId(2)); 861 assertThat(persistentIdDisplayName.toString()).isEqualTo(displayName.toString()); 862 } 863 864 @Test onAppsOnVirtualDeviceChanged_singleVirtualDevice_listenersNotified()865 public void onAppsOnVirtualDeviceChanged_singleVirtualDevice_listenersNotified() { 866 ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2)); 867 mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener); 868 869 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uids); 870 TestableLooper.get(this).processAllMessages(); 871 872 verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged(uids); 873 } 874 875 @Test onAppsOnVirtualDeviceChanged_multipleVirtualDevices_listenersNotified()876 public void onAppsOnVirtualDeviceChanged_multipleVirtualDevices_listenersNotified() { 877 createVirtualDevice(VIRTUAL_DEVICE_ID_2, DEVICE_OWNER_UID_2); 878 879 ArraySet<Integer> uidsOnDevice1 = new ArraySet<>(Arrays.asList(UID_1, UID_2)); 880 ArraySet<Integer> uidsOnDevice2 = new ArraySet<>(Arrays.asList(UID_3, UID_4)); 881 mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener); 882 883 // Notifies that the running apps on the first virtual device has changed. 884 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uidsOnDevice1); 885 TestableLooper.get(this).processAllMessages(); 886 verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged( 887 new ArraySet<>(Arrays.asList(UID_1, UID_2))); 888 889 // Notifies that the running apps on the second virtual device has changed. 890 mVdms.notifyRunningAppsChanged(VIRTUAL_DEVICE_ID_2, uidsOnDevice2); 891 TestableLooper.get(this).processAllMessages(); 892 // The union of the apps running on both virtual devices are sent to the listeners. 893 verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged( 894 new ArraySet<>(Arrays.asList(UID_1, UID_2, UID_3, UID_4))); 895 896 // Notifies that the running apps on the first virtual device has changed again. 897 uidsOnDevice1.remove(UID_2); 898 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uidsOnDevice1); 899 mLocalService.onAppsOnVirtualDeviceChanged(); 900 TestableLooper.get(this).processAllMessages(); 901 // The union of the apps running on both virtual devices are sent to the listeners. 902 verify(mAppsOnVirtualDeviceListener).onAppsOnAnyVirtualDeviceChanged( 903 new ArraySet<>(Arrays.asList(UID_1, UID_3, UID_4))); 904 905 // Notifies that the running apps on the first virtual device has changed but with the same 906 // set of UIDs. 907 mVdms.notifyRunningAppsChanged(mDeviceImpl.getDeviceId(), uidsOnDevice1); 908 mLocalService.onAppsOnVirtualDeviceChanged(); 909 TestableLooper.get(this).processAllMessages(); 910 // Listeners should not be notified. 911 verifyNoMoreInteractions(mAppsOnVirtualDeviceListener); 912 } 913 914 @Test onVirtualDisplayCreatedLocked_wakeLockIsAcquired()915 public void onVirtualDisplayCreatedLocked_wakeLockIsAcquired() throws RemoteException { 916 verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(), 917 nullable(String.class), nullable(String.class), nullable(WorkSource.class), 918 nullable(String.class), anyInt(), eq(null)); 919 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 920 verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(), 921 nullable(String.class), nullable(String.class), nullable(WorkSource.class), 922 nullable(String.class), eq(DISPLAY_ID_1), eq(null)); 923 } 924 925 @Test onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired()926 public void onVirtualDisplayCreatedLocked_duplicateCalls_onlyOneWakeLockIsAcquired() 927 throws RemoteException { 928 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 929 assertThrows(IllegalStateException.class, 930 () -> addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1)); 931 TestableLooper.get(this).processAllMessages(); 932 verify(mIPowerManagerMock).acquireWakeLock(any(Binder.class), anyInt(), 933 nullable(String.class), nullable(String.class), nullable(WorkSource.class), 934 nullable(String.class), eq(DISPLAY_ID_1), eq(null)); 935 } 936 937 @Test onVirtualDisplayRemovedLocked_wakeLockIsReleased()938 public void onVirtualDisplayRemovedLocked_wakeLockIsReleased() throws RemoteException { 939 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 940 ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class); 941 TestableLooper.get(this).processAllMessages(); 942 verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(), 943 anyInt(), 944 nullable(String.class), nullable(String.class), nullable(WorkSource.class), 945 nullable(String.class), eq(DISPLAY_ID_1), eq(null)); 946 947 IBinder wakeLock = wakeLockCaptor.getValue(); 948 mDeviceImpl.onVirtualDisplayRemoved(DISPLAY_ID_1); 949 verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt()); 950 } 951 952 @Test addVirtualDisplay_displayNotReleased_wakeLockIsReleased()953 public void addVirtualDisplay_displayNotReleased_wakeLockIsReleased() throws RemoteException { 954 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 955 ArgumentCaptor<IBinder> wakeLockCaptor = ArgumentCaptor.forClass(IBinder.class); 956 TestableLooper.get(this).processAllMessages(); 957 verify(mIPowerManagerMock).acquireWakeLock(wakeLockCaptor.capture(), 958 anyInt(), 959 nullable(String.class), nullable(String.class), nullable(WorkSource.class), 960 nullable(String.class), eq(DISPLAY_ID_1), eq(null)); 961 IBinder wakeLock = wakeLockCaptor.getValue(); 962 963 // Close the VirtualDevice without first notifying it of the VirtualDisplay removal. 964 mDeviceImpl.close(); 965 verify(mIPowerManagerMock).releaseWakeLock(eq(wakeLock), anyInt()); 966 } 967 968 @Test createVirtualDpad_noDisplay_failsSecurityException()969 public void createVirtualDpad_noDisplay_failsSecurityException() { 970 assertThrows(SecurityException.class, 971 () -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER)); 972 } 973 974 @Test createVirtualKeyboard_noDisplay_failsSecurityException()975 public void createVirtualKeyboard_noDisplay_failsSecurityException() { 976 assertThrows(SecurityException.class, 977 () -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER)); 978 } 979 980 @Test createVirtualMouse_noDisplay_failsSecurityException()981 public void createVirtualMouse_noDisplay_failsSecurityException() { 982 assertThrows(SecurityException.class, 983 () -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER)); 984 } 985 986 @Test createVirtualTouchscreen_noDisplay_failsSecurityException()987 public void createVirtualTouchscreen_noDisplay_failsSecurityException() { 988 assertThrows(SecurityException.class, 989 () -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER)); 990 } 991 992 @Test createVirtualTouchscreen_zeroDisplayDimension_failsIllegalArgumentException()993 public void createVirtualTouchscreen_zeroDisplayDimension_failsIllegalArgumentException() { 994 assertThrows(IllegalArgumentException.class, 995 () -> new VirtualTouchscreenConfig.Builder( 996 /* touchscrenWidth= */ 0, /* touchscreenHeight= */ 0)); 997 } 998 999 @Test createVirtualTouchscreen_negativeDisplayDimension_failsIllegalArgumentException()1000 public void createVirtualTouchscreen_negativeDisplayDimension_failsIllegalArgumentException() { 1001 assertThrows(IllegalArgumentException.class, 1002 () -> new VirtualTouchscreenConfig.Builder( 1003 /* touchscrenWidth= */ -100, /* touchscreenHeight= */ -100)); 1004 } 1005 1006 @Test createVirtualTouchscreen_positiveDisplayDimension_successful()1007 public void createVirtualTouchscreen_positiveDisplayDimension_successful() { 1008 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1009 VirtualTouchscreenConfig positiveConfig = 1010 new VirtualTouchscreenConfig.Builder( 1011 /* touchscrenWidth= */ 600, /* touchscreenHeight= */ 800) 1012 .setVendorId(VENDOR_ID) 1013 .setProductId(PRODUCT_ID) 1014 .setInputDeviceName(DEVICE_NAME_1) 1015 .setAssociatedDisplayId(DISPLAY_ID_1) 1016 .build(); 1017 mDeviceImpl.createVirtualTouchscreen(positiveConfig, BINDER); 1018 assertWithMessage( 1019 "Virtual touchscreen should create input device descriptor on successful creation" 1020 + ".").that(mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1021 } 1022 1023 @Test createVirtualNavigationTouchpad_noDisplay_failsSecurityException()1024 public void createVirtualNavigationTouchpad_noDisplay_failsSecurityException() { 1025 assertThrows(SecurityException.class, 1026 () -> mDeviceImpl.createVirtualNavigationTouchpad(NAVIGATION_TOUCHPAD_CONFIG, 1027 BINDER)); 1028 } 1029 1030 @Test createVirtualNavigationTouchpad_zeroDisplayDimension_failsWithException()1031 public void createVirtualNavigationTouchpad_zeroDisplayDimension_failsWithException() { 1032 assertThrows(IllegalArgumentException.class, 1033 () -> new VirtualNavigationTouchpadConfig.Builder( 1034 /* touchpadHeight= */ 0, /* touchpadWidth= */ 0)); 1035 } 1036 1037 @Test createVirtualNavigationTouchpad_negativeDisplayDimension_failsWithException()1038 public void createVirtualNavigationTouchpad_negativeDisplayDimension_failsWithException() { 1039 assertThrows(IllegalArgumentException.class, 1040 () -> new VirtualNavigationTouchpadConfig.Builder( 1041 /* touchpadHeight= */ -50, /* touchpadWidth= */ 50)); 1042 } 1043 1044 @Test createVirtualNavigationTouchpad_positiveDisplayDimension_successful()1045 public void createVirtualNavigationTouchpad_positiveDisplayDimension_successful() { 1046 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1047 VirtualNavigationTouchpadConfig positiveConfig = 1048 new VirtualNavigationTouchpadConfig.Builder( 1049 /* touchpadHeight= */ 50, /* touchpadWidth= */ 50) 1050 .setVendorId(VENDOR_ID) 1051 .setProductId(PRODUCT_ID) 1052 .setInputDeviceName(DEVICE_NAME_1) 1053 .setAssociatedDisplayId(DISPLAY_ID_1) 1054 .build(); 1055 mDeviceImpl.createVirtualNavigationTouchpad(positiveConfig, BINDER); 1056 assertWithMessage( 1057 "Virtual navigation touchpad should create input device descriptor on successful " 1058 + "creation" 1059 + ".").that(mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1060 } 1061 1062 @Test onAudioSessionStarting_noDisplay_failsSecurityException()1063 public void onAudioSessionStarting_noDisplay_failsSecurityException() { 1064 assertThrows(SecurityException.class, 1065 () -> mDeviceImpl.onAudioSessionStarting( 1066 DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback)); 1067 } 1068 1069 @Test createVirtualDpad_noPermission_failsSecurityException()1070 public void createVirtualDpad_noPermission_failsSecurityException() { 1071 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1072 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1073 assertThrows(SecurityException.class, 1074 () -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER)); 1075 } 1076 } 1077 1078 @Test createVirtualKeyboard_noPermission_failsSecurityException()1079 public void createVirtualKeyboard_noPermission_failsSecurityException() { 1080 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1081 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1082 assertThrows(SecurityException.class, 1083 () -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER)); 1084 } 1085 } 1086 1087 @Test createVirtualMouse_noPermission_failsSecurityException()1088 public void createVirtualMouse_noPermission_failsSecurityException() { 1089 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1090 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1091 assertThrows(SecurityException.class, 1092 () -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER)); 1093 } 1094 } 1095 1096 @Test createVirtualTouchscreen_noPermission_failsSecurityException()1097 public void createVirtualTouchscreen_noPermission_failsSecurityException() { 1098 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1099 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1100 assertThrows(SecurityException.class, 1101 () -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER)); 1102 } 1103 } 1104 1105 @Test createVirtualNavigationTouchpad_noPermission_failsSecurityException()1106 public void createVirtualNavigationTouchpad_noPermission_failsSecurityException() { 1107 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1108 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1109 assertThrows(SecurityException.class, 1110 () -> mDeviceImpl.createVirtualNavigationTouchpad(NAVIGATION_TOUCHPAD_CONFIG, 1111 BINDER)); 1112 } 1113 } 1114 1115 @Test onAudioSessionStarting_noPermission_failsSecurityException()1116 public void onAudioSessionStarting_noPermission_failsSecurityException() { 1117 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1118 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1119 assertThrows(SecurityException.class, 1120 () -> mDeviceImpl.onAudioSessionStarting( 1121 DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback)); 1122 } 1123 } 1124 1125 @Test onAudioSessionEnded_noPermission_failsSecurityException()1126 public void onAudioSessionEnded_noPermission_failsSecurityException() { 1127 try (DropShellPermissionsTemporarily drop = new DropShellPermissionsTemporarily()) { 1128 assertThrows(SecurityException.class, () -> mDeviceImpl.onAudioSessionEnded()); 1129 } 1130 } 1131 1132 @Test createVirtualDpad_hasDisplay_obtainFileDescriptor()1133 public void createVirtualDpad_hasDisplay_obtainFileDescriptor() { 1134 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1135 mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER); 1136 assertWithMessage("Virtual dpad should register fd when the display matches").that( 1137 mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1138 verify(mNativeWrapperMock).openUinputDpad(eq(DEVICE_NAME_1), eq(VENDOR_ID), eq(PRODUCT_ID), 1139 anyString()); 1140 } 1141 1142 @Test createVirtualKeyboard_hasDisplay_obtainFileDescriptor()1143 public void createVirtualKeyboard_hasDisplay_obtainFileDescriptor() { 1144 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1145 mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER); 1146 assertWithMessage("Virtual keyboard should register fd when the display matches").that( 1147 mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1148 verify(mNativeWrapperMock).openUinputKeyboard(eq(DEVICE_NAME_1), eq(VENDOR_ID), 1149 eq(PRODUCT_ID), anyString()); 1150 } 1151 1152 @Test createVirtualKeyboard_keyboardCreated_localeUpdated()1153 public void createVirtualKeyboard_keyboardCreated_localeUpdated() { 1154 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1155 mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER); 1156 assertWithMessage("Virtual keyboard should register fd when the display matches") 1157 .that(mInputController.getInputDeviceDescriptors()) 1158 .isNotEmpty(); 1159 verify(mNativeWrapperMock).openUinputKeyboard(eq(DEVICE_NAME_1), eq(VENDOR_ID), 1160 eq(PRODUCT_ID), anyString()); 1161 assertThat(mDeviceImpl.getDeviceLocaleList()).isEqualTo( 1162 LocaleList.forLanguageTags(KEYBOARD_CONFIG.getLanguageTag())); 1163 } 1164 1165 @Test createVirtualKeyboard_keyboardWithoutExplicitLayoutInfo_localeUpdatedWithDefault()1166 public void createVirtualKeyboard_keyboardWithoutExplicitLayoutInfo_localeUpdatedWithDefault() { 1167 VirtualKeyboardConfig configWithoutExplicitLayoutInfo = 1168 new VirtualKeyboardConfig.Builder() 1169 .setVendorId(VENDOR_ID) 1170 .setProductId(PRODUCT_ID) 1171 .setInputDeviceName(DEVICE_NAME_1) 1172 .setAssociatedDisplayId(DISPLAY_ID_1) 1173 .build(); 1174 1175 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1176 mDeviceImpl.createVirtualKeyboard(configWithoutExplicitLayoutInfo, BINDER); 1177 assertWithMessage("Virtual keyboard should register fd when the display matches") 1178 .that(mInputController.getInputDeviceDescriptors()) 1179 .isNotEmpty(); 1180 verify(mNativeWrapperMock).openUinputKeyboard(eq(DEVICE_NAME_1), eq(VENDOR_ID), 1181 eq(PRODUCT_ID), anyString()); 1182 assertThat(mDeviceImpl.getDeviceLocaleList()).isEqualTo( 1183 LocaleList.forLanguageTags(VirtualKeyboardConfig.DEFAULT_LANGUAGE_TAG)); 1184 } 1185 1186 @Test virtualDeviceWithoutKeyboard_noLocaleUpdate()1187 public void virtualDeviceWithoutKeyboard_noLocaleUpdate() { 1188 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1189 1190 // no preceding call to createVirtualKeyboard() 1191 assertThat(mDeviceImpl.getDeviceLocaleList()).isNull(); 1192 } 1193 1194 @Test createVirtualMouse_hasDisplay_obtainFileDescriptor()1195 public void createVirtualMouse_hasDisplay_obtainFileDescriptor() { 1196 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1197 mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER); 1198 assertWithMessage("Virtual mouse should register fd when the display matches").that( 1199 mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1200 verify(mNativeWrapperMock).openUinputMouse(eq(DEVICE_NAME_1), eq(VENDOR_ID), eq(PRODUCT_ID), 1201 anyString()); 1202 } 1203 1204 @Test createVirtualTouchscreen_hasDisplay_obtainFileDescriptor()1205 public void createVirtualTouchscreen_hasDisplay_obtainFileDescriptor() { 1206 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1207 mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER); 1208 assertWithMessage("Virtual touchscreen should register fd when the display matches").that( 1209 mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1210 verify(mNativeWrapperMock).openUinputTouchscreen(eq(DEVICE_NAME_1), eq(VENDOR_ID), 1211 eq(PRODUCT_ID), anyString(), eq(HEIGHT), eq(WIDTH)); 1212 } 1213 1214 @Test createVirtualNavigationTouchpad_hasDisplay_obtainFileDescriptor()1215 public void createVirtualNavigationTouchpad_hasDisplay_obtainFileDescriptor() { 1216 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1217 mDeviceImpl.createVirtualNavigationTouchpad(NAVIGATION_TOUCHPAD_CONFIG, BINDER); 1218 assertWithMessage("Virtual navigation touchpad should register fd when the display matches") 1219 .that( 1220 mInputController.getInputDeviceDescriptors()).isNotEmpty(); 1221 verify(mNativeWrapperMock).openUinputTouchscreen(eq(DEVICE_NAME_1), eq(VENDOR_ID), 1222 eq(PRODUCT_ID), anyString(), eq(HEIGHT), eq(WIDTH)); 1223 } 1224 1225 @Test createVirtualKeyboard_inputDeviceId_obtainFromInputController()1226 public void createVirtualKeyboard_inputDeviceId_obtainFromInputController() { 1227 final int fd = 1; 1228 mInputController.addDeviceForTesting(BINDER, fd, 1229 InputController.InputDeviceDescriptor.TYPE_KEYBOARD, DISPLAY_ID_1, PHYS, 1230 DEVICE_NAME_1, INPUT_DEVICE_ID); 1231 assertWithMessage( 1232 "InputController should return device id from InputDeviceDescriptor").that( 1233 mInputController.getInputDeviceId(BINDER)).isEqualTo(INPUT_DEVICE_ID); 1234 } 1235 1236 @Test onAudioSessionStarting_hasVirtualAudioController()1237 public void onAudioSessionStarting_hasVirtualAudioController() { 1238 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1239 1240 mDeviceImpl.onAudioSessionStarting(DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback); 1241 1242 assertThat(mDeviceImpl.getVirtualAudioControllerForTesting()).isNotNull(); 1243 } 1244 1245 @Test onAudioSessionEnded_noVirtualAudioController()1246 public void onAudioSessionEnded_noVirtualAudioController() { 1247 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1248 mDeviceImpl.onAudioSessionStarting(DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback); 1249 1250 mDeviceImpl.onAudioSessionEnded(); 1251 1252 assertThat(mDeviceImpl.getVirtualAudioControllerForTesting()).isNull(); 1253 } 1254 1255 @Test close_cleanVirtualAudioController()1256 public void close_cleanVirtualAudioController() { 1257 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1258 mDeviceImpl.onAudioSessionStarting(DISPLAY_ID_1, mRoutingCallback, mConfigChangedCallback); 1259 1260 mDeviceImpl.close(); 1261 1262 assertThat(mDeviceImpl.getVirtualAudioControllerForTesting()).isNull(); 1263 } 1264 1265 @Test close_cleanSensorController()1266 public void close_cleanSensorController() { 1267 mSensorController.addSensorForTesting( 1268 BINDER, SENSOR_HANDLE, Sensor.TYPE_ACCELEROMETER, DEVICE_NAME_1); 1269 1270 mDeviceImpl.close(); 1271 1272 assertThat(mSensorController.getSensorDescriptors()).isEmpty(); 1273 verify(mSensorManagerInternalMock).removeRuntimeSensor(SENSOR_HANDLE); 1274 } 1275 1276 @Test closedDevice_lateCallToRunningAppsChanged_isIgnored()1277 public void closedDevice_lateCallToRunningAppsChanged_isIgnored() { 1278 mLocalService.registerAppsOnVirtualDeviceListener(mAppsOnVirtualDeviceListener); 1279 int deviceId = mDeviceImpl.getDeviceId(); 1280 mDeviceImpl.close(); 1281 mVdms.notifyRunningAppsChanged(deviceId, Sets.newArraySet(UID_1)); 1282 TestableLooper.get(this).processAllMessages(); 1283 verify(mAppsOnVirtualDeviceListener, never()).onAppsOnAnyVirtualDeviceChanged(any()); 1284 } 1285 1286 @Test sendKeyEvent_noFd()1287 public void sendKeyEvent_noFd() { 1288 assertThat(mDeviceImpl.sendKeyEvent(BINDER, 1289 new VirtualKeyEvent.Builder() 1290 .setKeyCode(KeyEvent.KEYCODE_A) 1291 .setAction(VirtualKeyEvent.ACTION_DOWN) 1292 .build())) 1293 .isFalse(); 1294 } 1295 1296 @Test sendKeyEvent_hasFd_writesEvent()1297 public void sendKeyEvent_hasFd_writesEvent() { 1298 final int fd = 1; 1299 final int keyCode = KeyEvent.KEYCODE_A; 1300 final int action = VirtualKeyEvent.ACTION_UP; 1301 final long eventTimeNanos = 5000L; 1302 mInputController.addDeviceForTesting(BINDER, fd, 1303 InputController.InputDeviceDescriptor.TYPE_KEYBOARD, DISPLAY_ID_1, PHYS, 1304 DEVICE_NAME_1, INPUT_DEVICE_ID); 1305 1306 assertThat(mDeviceImpl.sendKeyEvent(BINDER, 1307 new VirtualKeyEvent.Builder() 1308 .setKeyCode(keyCode) 1309 .setAction(action) 1310 .setEventTimeNanos(eventTimeNanos) 1311 .build())) 1312 .isTrue(); 1313 verify(mNativeWrapperMock).writeKeyEvent(fd, keyCode, action, eventTimeNanos); 1314 } 1315 1316 @Test sendButtonEvent_noFd()1317 public void sendButtonEvent_noFd() { 1318 assertThat(mDeviceImpl.sendButtonEvent(BINDER, 1319 new VirtualMouseButtonEvent.Builder() 1320 .setButtonCode(VirtualMouseButtonEvent.BUTTON_BACK) 1321 .setAction(VirtualMouseButtonEvent.ACTION_BUTTON_PRESS) 1322 .build())) 1323 .isFalse(); 1324 } 1325 1326 @Test sendButtonEvent_hasFd_writesEvent()1327 public void sendButtonEvent_hasFd_writesEvent() { 1328 final int fd = 1; 1329 final int buttonCode = VirtualMouseButtonEvent.BUTTON_BACK; 1330 final int action = VirtualMouseButtonEvent.ACTION_BUTTON_PRESS; 1331 final long eventTimeNanos = 5000L; 1332 mInputController.addDeviceForTesting(BINDER, fd, 1333 InputController.InputDeviceDescriptor.TYPE_MOUSE, DISPLAY_ID_1, PHYS, 1334 DEVICE_NAME_1, INPUT_DEVICE_ID); 1335 assertThat(mDeviceImpl.sendButtonEvent(BINDER, 1336 new VirtualMouseButtonEvent.Builder() 1337 .setButtonCode(buttonCode) 1338 .setAction(action) 1339 .setEventTimeNanos(eventTimeNanos) 1340 .build())) 1341 .isTrue(); 1342 verify(mNativeWrapperMock).writeButtonEvent(fd, buttonCode, action, eventTimeNanos); 1343 } 1344 1345 @Test sendRelativeEvent_noFd()1346 public void sendRelativeEvent_noFd() { 1347 assertThat(mDeviceImpl.sendRelativeEvent(BINDER, 1348 new VirtualMouseRelativeEvent.Builder() 1349 .setRelativeX(0.0f) 1350 .setRelativeY(0.0f) 1351 .build())) 1352 .isFalse(); 1353 } 1354 1355 @Test sendRelativeEvent_hasFd_writesEvent()1356 public void sendRelativeEvent_hasFd_writesEvent() { 1357 final int fd = 1; 1358 final float x = -0.2f; 1359 final float y = 0.7f; 1360 final long eventTimeNanos = 5000L; 1361 mInputController.addDeviceForTesting(BINDER, fd, 1362 InputController.InputDeviceDescriptor.TYPE_MOUSE, DISPLAY_ID_1, PHYS, DEVICE_NAME_1, 1363 INPUT_DEVICE_ID); 1364 assertThat(mDeviceImpl.sendRelativeEvent(BINDER, 1365 new VirtualMouseRelativeEvent.Builder() 1366 .setRelativeX(x) 1367 .setRelativeY(y) 1368 .setEventTimeNanos(eventTimeNanos) 1369 .build())) 1370 .isTrue(); 1371 verify(mNativeWrapperMock).writeRelativeEvent(fd, x, y, eventTimeNanos); 1372 } 1373 1374 1375 @Test sendScrollEvent_noFd()1376 public void sendScrollEvent_noFd() { 1377 assertThat(mDeviceImpl.sendScrollEvent(BINDER, 1378 new VirtualMouseScrollEvent.Builder() 1379 .setXAxisMovement(-1f) 1380 .setYAxisMovement(1f) 1381 .build())) 1382 .isFalse(); 1383 } 1384 1385 @Test sendScrollEvent_hasFd_writesEvent()1386 public void sendScrollEvent_hasFd_writesEvent() { 1387 final int fd = 1; 1388 final float x = 0.5f; 1389 final float y = 1f; 1390 final long eventTimeNanos = 5000L; 1391 mInputController.addDeviceForTesting(BINDER, fd, 1392 InputController.InputDeviceDescriptor.TYPE_MOUSE, DISPLAY_ID_1, PHYS, DEVICE_NAME_1, 1393 INPUT_DEVICE_ID); 1394 assertThat(mDeviceImpl.sendScrollEvent(BINDER, 1395 new VirtualMouseScrollEvent.Builder() 1396 .setXAxisMovement(x) 1397 .setYAxisMovement(y) 1398 .setEventTimeNanos(eventTimeNanos) 1399 .build())) 1400 .isTrue(); 1401 verify(mNativeWrapperMock).writeScrollEvent(fd, x, y, eventTimeNanos); 1402 } 1403 1404 1405 @Test sendTouchEvent_noFd()1406 public void sendTouchEvent_noFd() { 1407 assertThat(mDeviceImpl.sendTouchEvent(BINDER, 1408 new VirtualTouchEvent.Builder() 1409 .setX(0.0f) 1410 .setY(0.0f) 1411 .setAction(VirtualTouchEvent.ACTION_UP) 1412 .setPointerId(1) 1413 .setToolType(VirtualTouchEvent.TOOL_TYPE_FINGER) 1414 .build())) 1415 .isFalse(); 1416 } 1417 1418 @Test sendTouchEvent_hasFd_writesEvent_withoutPressureOrMajorAxisSize()1419 public void sendTouchEvent_hasFd_writesEvent_withoutPressureOrMajorAxisSize() { 1420 final int fd = 1; 1421 final int pointerId = 5; 1422 final int toolType = VirtualTouchEvent.TOOL_TYPE_FINGER; 1423 final float x = 100.5f; 1424 final float y = 200.5f; 1425 final int action = VirtualTouchEvent.ACTION_UP; 1426 final long eventTimeNanos = 5000L; 1427 mInputController.addDeviceForTesting(BINDER, fd, 1428 InputController.InputDeviceDescriptor.TYPE_TOUCHSCREEN, DISPLAY_ID_1, PHYS, 1429 DEVICE_NAME_1, INPUT_DEVICE_ID); 1430 assertThat(mDeviceImpl.sendTouchEvent(BINDER, 1431 new VirtualTouchEvent.Builder() 1432 .setX(x) 1433 .setY(y) 1434 .setAction(action) 1435 .setPointerId(pointerId) 1436 .setToolType(toolType) 1437 .setEventTimeNanos(eventTimeNanos) 1438 .build())) 1439 .isTrue(); 1440 verify(mNativeWrapperMock).writeTouchEvent(fd, pointerId, toolType, action, x, y, Float.NaN, 1441 Float.NaN, eventTimeNanos); 1442 } 1443 1444 @Test sendTouchEvent_hasFd_writesEvent()1445 public void sendTouchEvent_hasFd_writesEvent() { 1446 final int fd = 1; 1447 final int pointerId = 5; 1448 final int toolType = VirtualTouchEvent.TOOL_TYPE_FINGER; 1449 final float x = 100.5f; 1450 final float y = 200.5f; 1451 final int action = VirtualTouchEvent.ACTION_UP; 1452 final float pressure = 1.0f; 1453 final float majorAxisSize = 10.0f; 1454 final long eventTimeNanos = 5000L; 1455 mInputController.addDeviceForTesting(BINDER, fd, 1456 InputController.InputDeviceDescriptor.TYPE_TOUCHSCREEN, DISPLAY_ID_1, PHYS, 1457 DEVICE_NAME_1, INPUT_DEVICE_ID); 1458 assertThat(mDeviceImpl.sendTouchEvent(BINDER, 1459 new VirtualTouchEvent.Builder() 1460 .setX(x) 1461 .setY(y) 1462 .setAction(action) 1463 .setPointerId(pointerId) 1464 .setToolType(toolType) 1465 .setPressure(pressure) 1466 .setMajorAxisSize(majorAxisSize) 1467 .setEventTimeNanos(eventTimeNanos) 1468 .build())) 1469 .isTrue(); 1470 verify(mNativeWrapperMock).writeTouchEvent(fd, pointerId, toolType, action, x, y, pressure, 1471 majorAxisSize, eventTimeNanos); 1472 } 1473 1474 @Test setShowPointerIcon_setsValueForAllDisplays()1475 public void setShowPointerIcon_setsValueForAllDisplays() { 1476 addVirtualDisplay(mDeviceImpl, 1); 1477 addVirtualDisplay(mDeviceImpl, 2); 1478 addVirtualDisplay(mDeviceImpl, 3); 1479 VirtualMouseConfig config1 = new VirtualMouseConfig.Builder() 1480 .setAssociatedDisplayId(1) 1481 .setInputDeviceName(DEVICE_NAME_1) 1482 .setVendorId(VENDOR_ID) 1483 .setProductId(PRODUCT_ID) 1484 .build(); 1485 VirtualMouseConfig config2 = new VirtualMouseConfig.Builder() 1486 .setAssociatedDisplayId(2) 1487 .setInputDeviceName(DEVICE_NAME_2) 1488 .setVendorId(VENDOR_ID) 1489 .setProductId(PRODUCT_ID) 1490 .build(); 1491 VirtualMouseConfig config3 = new VirtualMouseConfig.Builder() 1492 .setAssociatedDisplayId(3) 1493 .setInputDeviceName(DEVICE_NAME_3) 1494 .setVendorId(VENDOR_ID) 1495 .setProductId(PRODUCT_ID) 1496 .build(); 1497 1498 mDeviceImpl.createVirtualMouse(config1, BINDER); 1499 mDeviceImpl.createVirtualMouse(config2, BINDER); 1500 mDeviceImpl.createVirtualMouse(config3, BINDER); 1501 clearInvocations(mInputManagerInternalMock); 1502 mDeviceImpl.setShowPointerIcon(false); 1503 1504 verify(mInputManagerInternalMock, times(3)).setPointerIconVisible(eq(false), anyInt()); 1505 verify(mInputManagerInternalMock, never()).setPointerIconVisible(eq(true), anyInt()); 1506 mDeviceImpl.setShowPointerIcon(true); 1507 verify(mInputManagerInternalMock, times(3)).setPointerIconVisible(eq(true), anyInt()); 1508 } 1509 1510 @Test openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity()1511 public void openNonBlockedAppOnVirtualDisplay_doesNotStartBlockedAlertActivity() { 1512 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1513 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1514 DISPLAY_ID_1); 1515 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1516 1517 ActivityInfo activityInfo = getActivityInfo( 1518 NONBLOCKED_APP_PACKAGE_NAME, 1519 NONBLOCKED_APP_PACKAGE_NAME, 1520 /* displayOnRemoteDevices */ true, 1521 /* targetDisplayCategory */ null); 1522 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1523 activityInfo, mAssociationInfo.getDisplayName()); 1524 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1525 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1526 1527 verify(mContext, never()).startActivityAsUser(argThat(intent -> 1528 intent.filterEquals(blockedAppIntent)), any(), any()); 1529 } 1530 1531 @Test openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity()1532 public void openPermissionControllerOnVirtualDisplay_startBlockedAlertActivity() { 1533 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1534 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1535 DISPLAY_ID_1); 1536 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1537 1538 ActivityInfo activityInfo = getActivityInfo( 1539 PERMISSION_CONTROLLER_PACKAGE_NAME, 1540 PERMISSION_CONTROLLER_PACKAGE_NAME, 1541 /* displayOnRemoteDevices */ false, 1542 /* targetDisplayCategory */ null); 1543 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1544 activityInfo, mAssociationInfo.getDisplayName()); 1545 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1546 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1547 1548 verify(mContext).startActivityAsUser(argThat(intent -> 1549 intent.filterEquals(blockedAppIntent)), any(), any()); 1550 } 1551 1552 @Test openPermissionControllerOnVirtualDisplay_displayOnRemoteDevices_startsWhenFlagIsEnabled()1553 public void openPermissionControllerOnVirtualDisplay_displayOnRemoteDevices_startsWhenFlagIsEnabled() { 1554 mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS); 1555 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1556 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1557 DISPLAY_ID_1); 1558 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1559 1560 ActivityInfo activityInfo = getActivityInfo( 1561 PERMISSION_CONTROLLER_PACKAGE_NAME, 1562 PERMISSION_CONTROLLER_PACKAGE_NAME, 1563 /* displayOnRemoveDevices */ true, 1564 /* targetDisplayCategory */ null); 1565 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1566 activityInfo, mAssociationInfo.getDisplayName()); 1567 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1568 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1569 1570 verify(mContext, never()).startActivityAsUser(argThat(intent -> 1571 intent.filterEquals(blockedAppIntent)), any(), any()); 1572 } 1573 1574 @Test openPermissionControllerOnVirtualDisplay_dontDisplayOnRemoteDevices_startsWhenFlagIsEnabled()1575 public void openPermissionControllerOnVirtualDisplay_dontDisplayOnRemoteDevices_startsWhenFlagIsEnabled() { 1576 mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS); 1577 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1578 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1579 DISPLAY_ID_1); 1580 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1581 1582 ActivityInfo activityInfo = getActivityInfo( 1583 PERMISSION_CONTROLLER_PACKAGE_NAME, 1584 PERMISSION_CONTROLLER_PACKAGE_NAME, 1585 /* displayOnRemoveDevices */ false, 1586 /* targetDisplayCategory */ null); 1587 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1588 activityInfo, mAssociationInfo.getDisplayName()); 1589 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1590 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1591 1592 verify(mContext).startActivityAsUser(argThat(intent -> 1593 intent.filterEquals(blockedAppIntent)), any(), any()); 1594 } 1595 1596 @Test openSettingsOnVirtualDisplay_startBlockedAlertActivity()1597 public void openSettingsOnVirtualDisplay_startBlockedAlertActivity() { 1598 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1599 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1600 DISPLAY_ID_1); 1601 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1602 1603 ActivityInfo activityInfo = getActivityInfo( 1604 SETTINGS_PACKAGE_NAME, 1605 SETTINGS_PACKAGE_NAME, 1606 /* displayOnRemoteDevices */ true, 1607 /* targetDisplayCategory */ null); 1608 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1609 activityInfo, mAssociationInfo.getDisplayName()); 1610 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1611 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1612 1613 verify(mContext).startActivityAsUser(argThat(intent -> 1614 intent.filterEquals(blockedAppIntent)), any(), any()); 1615 } 1616 1617 @Test openVendingOnVirtualDisplay_startBlockedAlertActivity()1618 public void openVendingOnVirtualDisplay_startBlockedAlertActivity() { 1619 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1620 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1621 DISPLAY_ID_1); 1622 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1623 1624 ActivityInfo activityInfo = getActivityInfo( 1625 VENDING_PACKAGE_NAME, 1626 VENDING_PACKAGE_NAME, 1627 /* displayOnRemoteDevices */ true, 1628 /* targetDisplayCategory */ null); 1629 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1630 activityInfo, mAssociationInfo.getDisplayName()); 1631 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1632 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1633 1634 verify(mContext).startActivityAsUser(argThat(intent -> 1635 intent.filterEquals(blockedAppIntent)), any(), any()); 1636 } 1637 1638 @Test openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity()1639 public void openGoogleDialerOnVirtualDisplay_startBlockedAlertActivity() { 1640 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1641 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1642 DISPLAY_ID_1); 1643 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1644 1645 ActivityInfo activityInfo = getActivityInfo( 1646 GOOGLE_DIALER_PACKAGE_NAME, 1647 GOOGLE_DIALER_PACKAGE_NAME, 1648 /* displayOnRemoteDevices */ true, 1649 /* targetDisplayCategory */ null); 1650 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1651 activityInfo, mAssociationInfo.getDisplayName()); 1652 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1653 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1654 1655 verify(mContext).startActivityAsUser(argThat(intent -> 1656 intent.filterEquals(blockedAppIntent)), any(), any()); 1657 } 1658 1659 @Test openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity()1660 public void openGoogleMapsOnVirtualDisplay_startBlockedAlertActivity() { 1661 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1662 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1663 DISPLAY_ID_1); 1664 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1665 1666 ActivityInfo activityInfo = getActivityInfo( 1667 GOOGLE_MAPS_PACKAGE_NAME, 1668 GOOGLE_MAPS_PACKAGE_NAME, 1669 /* displayOnRemoteDevices */ true, 1670 /* targetDisplayCategory */ null); 1671 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1672 activityInfo, mAssociationInfo.getDisplayName()); 1673 gwpc.canActivityBeLaunched(activityInfo, blockedAppIntent, 1674 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false); 1675 1676 verify(mContext).startActivityAsUser(argThat(intent -> 1677 intent.filterEquals(blockedAppIntent)), any(), any()); 1678 } 1679 1680 @Test openNonBlockedAppOnMirrorDisplay_flagEnabled_cannotBeLaunched()1681 public void openNonBlockedAppOnMirrorDisplay_flagEnabled_cannotBeLaunched() { 1682 mSetFlagsRule.enableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); 1683 when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt())) 1684 .thenReturn(Display.DEFAULT_DISPLAY); 1685 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1686 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1687 DISPLAY_ID_1); 1688 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1689 1690 ActivityInfo activityInfo = getActivityInfo( 1691 NONBLOCKED_APP_PACKAGE_NAME, 1692 NONBLOCKED_APP_PACKAGE_NAME, 1693 /* displayOnRemoteDevices */ true, 1694 /* targetDisplayCategory */ null); 1695 assertThat(gwpc.canActivityBeLaunched(activityInfo, null, 1696 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/ false)) 1697 .isFalse(); 1698 // Verify that BlockedAppStreamingActivity also doesn't launch for mirror displays. 1699 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1700 activityInfo, mAssociationInfo.getDisplayName()); 1701 verify(mContext, never()).startActivityAsUser(argThat(intent -> 1702 intent.filterEquals(blockedAppIntent)), any(), any()); 1703 } 1704 1705 @Test openNonBlockedAppOnMirrorDisplay_flagDisabled_launchesActivity()1706 public void openNonBlockedAppOnMirrorDisplay_flagDisabled_launchesActivity() { 1707 mSetFlagsRule.disableFlags(Flags.FLAG_INTERACTIVE_SCREEN_MIRROR); 1708 when(mDisplayManagerInternalMock.getDisplayIdToMirror(anyInt())) 1709 .thenReturn(Display.DEFAULT_DISPLAY); 1710 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1711 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1712 DISPLAY_ID_1); 1713 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1714 1715 ActivityInfo activityInfo = getActivityInfo( 1716 NONBLOCKED_APP_PACKAGE_NAME, 1717 NONBLOCKED_APP_PACKAGE_NAME, 1718 /* displayOnRemoteDevices */ true, 1719 /* targetDisplayCategory */ null); 1720 assertThat(gwpc.canActivityBeLaunched(activityInfo, null, 1721 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/ false)) 1722 .isTrue(); 1723 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1724 activityInfo, mAssociationInfo.getDisplayName()); 1725 verify(mContext, never()).startActivityAsUser(argThat(intent -> 1726 intent.filterEquals(blockedAppIntent)), any(), any()); 1727 } 1728 1729 @Test registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified()1730 public void registerRunningAppsChangedListener_onRunningAppsChanged_listenersNotified() { 1731 ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2)); 1732 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1733 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1734 DISPLAY_ID_1); 1735 1736 gwpc.onRunningAppsChanged(uids); 1737 mDeviceImpl.onRunningAppsChanged(uids); 1738 1739 assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(1); 1740 verify(mRunningAppsChangedCallback).accept(new ArraySet<>(Arrays.asList(UID_1, UID_2))); 1741 } 1742 1743 @Test noRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException()1744 public void noRunningAppsChangedListener_onRunningAppsChanged_doesNotThrowException() { 1745 ArraySet<Integer> uids = new ArraySet<>(Arrays.asList(UID_1, UID_2)); 1746 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1747 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1748 DISPLAY_ID_1); 1749 gwpc.unregisterRunningAppsChangedListener(mDeviceImpl); 1750 1751 // This call should not throw any exceptions. 1752 gwpc.onRunningAppsChanged(uids); 1753 1754 assertThat(gwpc.getRunningAppsChangedListenersSizeForTesting()).isEqualTo(0); 1755 } 1756 1757 @Test canActivityBeLaunched_permissionDialog_flagDisabled_isBlocked()1758 public void canActivityBeLaunched_permissionDialog_flagDisabled_isBlocked() { 1759 mSetFlagsRule.disableFlags(Flags.FLAG_STREAM_PERMISSIONS); 1760 VirtualDeviceParams params = new VirtualDeviceParams.Builder().build(); 1761 mDeviceImpl.close(); 1762 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params); 1763 doNothing().when(mContext).startActivityAsUser(any(), any(), any()); 1764 1765 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1766 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1767 DISPLAY_ID_1); 1768 ComponentName permissionComponent = getPermissionDialogComponent(); 1769 ActivityInfo activityInfo = getActivityInfo( 1770 permissionComponent.getPackageName(), 1771 permissionComponent.getClassName(), 1772 /* displayOnRemoteDevices */ true, 1773 /* targetDisplayCategory */ null); 1774 assertThat(gwpc.canActivityBeLaunched(activityInfo, null, 1775 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false)) 1776 .isFalse(); 1777 1778 Intent blockedAppIntent = BlockedAppStreamingActivity.createIntent( 1779 activityInfo, mAssociationInfo.getDisplayName()); 1780 verify(mContext).startActivityAsUser(argThat(intent -> 1781 intent.filterEquals(blockedAppIntent)), any(), any()); 1782 } 1783 1784 @Test canActivityBeLaunched_permissionDialog_flagEnabled_isStreamed()1785 public void canActivityBeLaunched_permissionDialog_flagEnabled_isStreamed() { 1786 mSetFlagsRule.enableFlags(Flags.FLAG_STREAM_PERMISSIONS); 1787 VirtualDeviceParams params = new VirtualDeviceParams.Builder().build(); 1788 mDeviceImpl.close(); 1789 mDeviceImpl = createVirtualDevice(VIRTUAL_DEVICE_ID_1, DEVICE_OWNER_UID_1, params); 1790 1791 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1792 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1793 DISPLAY_ID_1); 1794 ComponentName permissionComponent = getPermissionDialogComponent(); 1795 ActivityInfo activityInfo = getActivityInfo( 1796 permissionComponent.getPackageName(), 1797 permissionComponent.getClassName(), 1798 /* displayOnRemoteDevices */ true, 1799 /* targetDisplayCategory */ null); 1800 assertThat(gwpc.canActivityBeLaunched(activityInfo, null, 1801 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false)) 1802 .isTrue(); 1803 } 1804 1805 @Test canActivityBeLaunched_activityCanLaunch()1806 public void canActivityBeLaunched_activityCanLaunch() { 1807 Intent intent = new Intent(ACTION_VIEW, Uri.parse(TEST_SITE)); 1808 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1809 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1810 DISPLAY_ID_1); 1811 ActivityInfo activityInfo = getActivityInfo( 1812 NONBLOCKED_APP_PACKAGE_NAME, 1813 NONBLOCKED_APP_PACKAGE_NAME, 1814 /* displayOnRemoteDevices */ true, 1815 /* targetDisplayCategory */ null); 1816 assertThat(gwpc.canActivityBeLaunched(activityInfo, intent, 1817 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false)) 1818 .isTrue(); 1819 } 1820 1821 @Test canActivityBeLaunched_intentInterceptedWhenRegistered_activityNoLaunch()1822 public void canActivityBeLaunched_intentInterceptedWhenRegistered_activityNoLaunch() 1823 throws RemoteException { 1824 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(TEST_SITE)); 1825 1826 IVirtualDeviceIntentInterceptor.Stub interceptor = 1827 mock(IVirtualDeviceIntentInterceptor.Stub.class); 1828 doNothing().when(interceptor).onIntentIntercepted(any()); 1829 doReturn(interceptor).when(interceptor).asBinder(); 1830 doReturn(interceptor).when(interceptor).queryLocalInterface(anyString()); 1831 1832 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1833 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1834 DISPLAY_ID_1); 1835 ActivityInfo activityInfo = getActivityInfo( 1836 NONBLOCKED_APP_PACKAGE_NAME, 1837 NONBLOCKED_APP_PACKAGE_NAME, 1838 /* displayOnRemoteDevices */ true, 1839 /* targetDisplayCategory */ null); 1840 1841 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_VIEW); 1842 intentFilter.addDataScheme(IntentFilter.SCHEME_HTTP); 1843 intentFilter.addDataScheme(IntentFilter.SCHEME_HTTPS); 1844 1845 // register interceptor and intercept intent 1846 mDeviceImpl.registerIntentInterceptor(interceptor, intentFilter); 1847 assertThat(gwpc.canActivityBeLaunched(activityInfo, intent, 1848 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false)) 1849 .isFalse(); 1850 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 1851 verify(interceptor).onIntentIntercepted(intentCaptor.capture()); 1852 Intent cIntent = intentCaptor.getValue(); 1853 assertThat(cIntent).isNotNull(); 1854 assertThat(cIntent.getAction()).isEqualTo(Intent.ACTION_VIEW); 1855 assertThat(cIntent.getData().toString()).isEqualTo(TEST_SITE); 1856 1857 // unregister interceptor and launch activity 1858 mDeviceImpl.unregisterIntentInterceptor(interceptor); 1859 assertThat(gwpc.canActivityBeLaunched(activityInfo, intent, 1860 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false)) 1861 .isTrue(); 1862 } 1863 1864 @Test canActivityBeLaunched_noMatchIntentFilter_activityLaunches()1865 public void canActivityBeLaunched_noMatchIntentFilter_activityLaunches() 1866 throws RemoteException { 1867 Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("testing")); 1868 1869 IVirtualDeviceIntentInterceptor.Stub interceptor = 1870 mock(IVirtualDeviceIntentInterceptor.Stub.class); 1871 doNothing().when(interceptor).onIntentIntercepted(any()); 1872 doReturn(interceptor).when(interceptor).asBinder(); 1873 doReturn(interceptor).when(interceptor).queryLocalInterface(anyString()); 1874 1875 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1876 GenericWindowPolicyController gwpc = mDeviceImpl.getDisplayWindowPolicyControllerForTest( 1877 DISPLAY_ID_1); 1878 ActivityInfo activityInfo = getActivityInfo( 1879 NONBLOCKED_APP_PACKAGE_NAME, 1880 NONBLOCKED_APP_PACKAGE_NAME, 1881 /* displayOnRemoteDevices */ true, 1882 /* targetDisplayCategory */ null); 1883 1884 IntentFilter intentFilter = new IntentFilter(Intent.ACTION_VIEW); 1885 intentFilter.addDataScheme("mailto"); 1886 1887 // register interceptor with different filter 1888 mDeviceImpl.registerIntentInterceptor(interceptor, intentFilter); 1889 1890 assertThat(gwpc.canActivityBeLaunched(activityInfo, intent, 1891 WindowConfiguration.WINDOWING_MODE_FULLSCREEN, DISPLAY_ID_1, /*isNewTask=*/false)) 1892 .isTrue(); 1893 } 1894 1895 @Test nonRestrictedActivityOnRestrictedVirtualDisplay_startBlockedAlertActivity()1896 public void nonRestrictedActivityOnRestrictedVirtualDisplay_startBlockedAlertActivity() { 1897 Intent blockedAppIntent = createRestrictedActivityBlockedIntent(Set.of("abc"), 1898 /* targetDisplayCategory= */ null); 1899 verify(mContext).startActivityAsUser(argThat(intent -> 1900 intent.filterEquals(blockedAppIntent)), any(), any()); 1901 } 1902 1903 @Test restrictedActivityOnRestrictedVirtualDisplay_doesNotStartBlockedAlertActivity()1904 public void restrictedActivityOnRestrictedVirtualDisplay_doesNotStartBlockedAlertActivity() { 1905 Intent blockedAppIntent = createRestrictedActivityBlockedIntent(Set.of("abc"), "abc"); 1906 verify(mContext, never()).startActivityAsUser(argThat(intent -> 1907 intent.filterEquals(blockedAppIntent)), any(), any()); 1908 } 1909 1910 @Test restrictedActivityOnNonRestrictedVirtualDisplay_startBlockedAlertActivity()1911 public void restrictedActivityOnNonRestrictedVirtualDisplay_startBlockedAlertActivity() { 1912 Intent blockedAppIntent = createRestrictedActivityBlockedIntent( 1913 /* displayCategories= */ Set.of(), "abc"); 1914 verify(mContext).startActivityAsUser(argThat(intent -> 1915 intent.filterEquals(blockedAppIntent)), any(), any()); 1916 } 1917 1918 @Test restrictedActivityNonMatchingRestrictedVirtualDisplay_startBlockedAlertActivity()1919 public void restrictedActivityNonMatchingRestrictedVirtualDisplay_startBlockedAlertActivity() { 1920 Intent blockedAppIntent = createRestrictedActivityBlockedIntent(Set.of("abc"), "def"); 1921 verify(mContext).startActivityAsUser(argThat(intent -> 1922 intent.filterEquals(blockedAppIntent)), any(), any()); 1923 } 1924 1925 @Test playSoundEffect_callsSoundEffectListener()1926 public void playSoundEffect_callsSoundEffectListener() throws Exception { 1927 mVdm.playSoundEffect(mDeviceImpl.getDeviceId(), AudioManager.FX_KEY_CLICK); 1928 1929 verify(mSoundEffectListener).onPlaySoundEffect(AudioManager.FX_KEY_CLICK); 1930 } 1931 1932 @Test getDisplayIdsForDevice_invalidDeviceId_emptyResult()1933 public void getDisplayIdsForDevice_invalidDeviceId_emptyResult() { 1934 ArraySet<Integer> displayIds = mLocalService.getDisplayIdsForDevice(VIRTUAL_DEVICE_ID_2); 1935 assertThat(displayIds).isEmpty(); 1936 } 1937 1938 @Test getDisplayIdsForDevice_noDisplays_emptyResult()1939 public void getDisplayIdsForDevice_noDisplays_emptyResult() { 1940 ArraySet<Integer> displayIds = mLocalService.getDisplayIdsForDevice(VIRTUAL_DEVICE_ID_1); 1941 assertThat(displayIds).isEmpty(); 1942 } 1943 1944 @Test getDisplayIdsForDevice_oneDisplay_resultContainsCorrectDisplayId()1945 public void getDisplayIdsForDevice_oneDisplay_resultContainsCorrectDisplayId() { 1946 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1947 ArraySet<Integer> displayIds = mLocalService.getDisplayIdsForDevice(VIRTUAL_DEVICE_ID_1); 1948 assertThat(displayIds).containsExactly(DISPLAY_ID_1); 1949 } 1950 1951 @Test getDisplayIdsForDevice_twoDisplays_resultContainsCorrectDisplayIds()1952 public void getDisplayIdsForDevice_twoDisplays_resultContainsCorrectDisplayIds() { 1953 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_1); 1954 addVirtualDisplay(mDeviceImpl, DISPLAY_ID_2); 1955 ArraySet<Integer> displayIds = mLocalService.getDisplayIdsForDevice(VIRTUAL_DEVICE_ID_1); 1956 assertThat(displayIds).containsExactly(DISPLAY_ID_1, DISPLAY_ID_2); 1957 } 1958 1959 @Test getPersistentIdForDevice_invalidDeviceId_returnsNull()1960 public void getPersistentIdForDevice_invalidDeviceId_returnsNull() { 1961 assertThat(mLocalService.getPersistentIdForDevice(DEVICE_ID_INVALID)).isNull(); 1962 assertThat(mLocalService.getPersistentIdForDevice(VIRTUAL_DEVICE_ID_2)).isNull(); 1963 } 1964 1965 @Test getPersistentIdForDevice_defaultDeviceId()1966 public void getPersistentIdForDevice_defaultDeviceId() { 1967 assertThat(mLocalService.getPersistentIdForDevice(DEVICE_ID_DEFAULT)).isEqualTo( 1968 VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT); 1969 } 1970 1971 @Test getPersistentIdForDevice_returnsCorrectId()1972 public void getPersistentIdForDevice_returnsCorrectId() { 1973 assertThat(mLocalService.getPersistentIdForDevice(VIRTUAL_DEVICE_ID_1)) 1974 .isEqualTo(mDeviceImpl.getPersistentDeviceId()); 1975 } 1976 createVirtualDevice(int virtualDeviceId, int ownerUid)1977 private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid) { 1978 VirtualDeviceParams params = new VirtualDeviceParams.Builder() 1979 .setBlockedActivities(getBlockedActivities()) 1980 .build(); 1981 return createVirtualDevice(virtualDeviceId, ownerUid, params); 1982 } 1983 createVirtualDevice(int virtualDeviceId, int ownerUid, VirtualDeviceParams params)1984 private VirtualDeviceImpl createVirtualDevice(int virtualDeviceId, int ownerUid, 1985 VirtualDeviceParams params) { 1986 VirtualDeviceImpl virtualDeviceImpl = 1987 new VirtualDeviceImpl( 1988 mContext, 1989 mAssociationInfo, 1990 mVdms, 1991 mVirtualDeviceLog, 1992 new Binder(), 1993 new AttributionSource( 1994 ownerUid, "com.android.virtualdevice.test", "virtualdevice"), 1995 virtualDeviceId, 1996 mInputController, 1997 mCameraAccessController, 1998 mPendingTrampolineCallback, 1999 mActivityListener, 2000 mSoundEffectListener, 2001 mRunningAppsChangedCallback, 2002 params, 2003 new DisplayManagerGlobal(mIDisplayManager), 2004 new VirtualCameraController(DEVICE_POLICY_DEFAULT, virtualDeviceId)); 2005 mVdms.addVirtualDevice(virtualDeviceImpl); 2006 assertThat(virtualDeviceImpl.getAssociationId()).isEqualTo(mAssociationInfo.getId()); 2007 assertThat(virtualDeviceImpl.getPersistentDeviceId()) 2008 .isEqualTo("companion:" + mAssociationInfo.getId()); 2009 return virtualDeviceImpl; 2010 } 2011 addVirtualDisplay(VirtualDeviceImpl virtualDevice, int displayId)2012 private void addVirtualDisplay(VirtualDeviceImpl virtualDevice, int displayId) { 2013 when(mDisplayManagerInternalMock.createVirtualDisplay(any(), eq(mVirtualDisplayCallback), 2014 eq(virtualDevice), any(), any())).thenReturn(displayId); 2015 virtualDevice.createVirtualDisplay(VIRTUAL_DISPLAY_CONFIG, mVirtualDisplayCallback, 2016 NONBLOCKED_APP_PACKAGE_NAME); 2017 final String uniqueId = UNIQUE_ID + displayId; 2018 doAnswer(inv -> { 2019 final DisplayInfo displayInfo = new DisplayInfo(); 2020 displayInfo.uniqueId = uniqueId; 2021 return displayInfo; 2022 }).when(mDisplayManagerInternalMock).getDisplayInfo(eq(displayId)); 2023 mInputManagerMockHelper.addDisplayIdMapping(uniqueId, displayId); 2024 } 2025 getPermissionDialogComponent()2026 private ComponentName getPermissionDialogComponent() { 2027 Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS); 2028 PackageManager packageManager = mContext.getPackageManager(); 2029 intent.setPackage(packageManager.getPermissionControllerPackageName()); 2030 return intent.resolveActivity(packageManager); 2031 } 2032 createAssociationInfo(int associationId, String deviceProfile)2033 private AssociationInfo createAssociationInfo(int associationId, String deviceProfile) { 2034 return createAssociationInfo( 2035 associationId, deviceProfile, /* displayName= */ deviceProfile); 2036 } 2037 createAssociationInfo(int associationId, String deviceProfile, CharSequence displayName)2038 private AssociationInfo createAssociationInfo(int associationId, String deviceProfile, 2039 CharSequence displayName) { 2040 return new AssociationInfo(associationId, /* userId= */ 0, /* packageName=*/ null, 2041 /* tag= */ null, MacAddress.BROADCAST_ADDRESS, displayName, deviceProfile, 2042 /* associatedDevice= */ null, /* selfManaged= */ true, 2043 /* notifyOnDeviceNearby= */ false, /* revoked= */ false, /* pending= */ false, 2044 /* timeApprovedMs= */0, /* lastTimeConnectedMs= */0, /* systemDataSyncFlags= */ -1); 2045 } 2046 2047 /** Helper class to drop permissions temporarily and restore them at the end of a test. */ 2048 static final class DropShellPermissionsTemporarily implements AutoCloseable { DropShellPermissionsTemporarily()2049 DropShellPermissionsTemporarily() { 2050 InstrumentationRegistry.getInstrumentation().getUiAutomation() 2051 .dropShellPermissionIdentity(); 2052 } 2053 2054 @Override close()2055 public void close() { 2056 InstrumentationRegistry.getInstrumentation().getUiAutomation() 2057 .adoptShellPermissionIdentity(); 2058 } 2059 } 2060 } 2061