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