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