• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
20 import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
21 import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_ENABLED;
22 import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
23 import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY;
24 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_CUSTOM;
25 import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAULT;
26 import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED;
27 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY;
28 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_AUDIO;
29 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_BLOCKED_ACTIVITY;
30 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CAMERA;
31 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_CLIPBOARD;
32 import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS;
33 
34 import android.annotation.NonNull;
35 import android.annotation.Nullable;
36 import android.annotation.RequiresPermission;
37 import android.annotation.StringRes;
38 import android.annotation.UserIdInt;
39 import android.app.Activity;
40 import android.app.ActivityOptions;
41 import android.app.PendingIntent;
42 import android.app.admin.DevicePolicyManager;
43 import android.app.compat.CompatChanges;
44 import android.companion.AssociationInfo;
45 import android.companion.AssociationRequest;
46 import android.companion.virtual.ActivityPolicyExemption;
47 import android.companion.virtual.IVirtualDevice;
48 import android.companion.virtual.IVirtualDeviceActivityListener;
49 import android.companion.virtual.IVirtualDeviceIntentInterceptor;
50 import android.companion.virtual.IVirtualDeviceSoundEffectListener;
51 import android.companion.virtual.VirtualDevice;
52 import android.companion.virtual.VirtualDeviceManager;
53 import android.companion.virtual.VirtualDeviceParams;
54 import android.companion.virtual.audio.IAudioConfigChangedCallback;
55 import android.companion.virtual.audio.IAudioRoutingCallback;
56 import android.companion.virtual.camera.VirtualCameraConfig;
57 import android.companion.virtual.sensor.VirtualSensor;
58 import android.companion.virtual.sensor.VirtualSensorAdditionalInfo;
59 import android.companion.virtual.sensor.VirtualSensorEvent;
60 import android.companion.virtualdevice.flags.Flags;
61 import android.compat.annotation.ChangeId;
62 import android.compat.annotation.EnabledAfter;
63 import android.content.AttributionSource;
64 import android.content.ComponentName;
65 import android.content.Context;
66 import android.content.Intent;
67 import android.content.IntentFilter;
68 import android.content.IntentSender;
69 import android.content.pm.ActivityInfo;
70 import android.content.pm.PackageManager;
71 import android.graphics.PointF;
72 import android.hardware.display.DisplayManager;
73 import android.hardware.display.DisplayManagerGlobal;
74 import android.hardware.display.DisplayManagerInternal;
75 import android.hardware.display.IVirtualDisplayCallback;
76 import android.hardware.display.VirtualDisplayConfig;
77 import android.hardware.input.VirtualDpadConfig;
78 import android.hardware.input.VirtualKeyEvent;
79 import android.hardware.input.VirtualKeyboardConfig;
80 import android.hardware.input.VirtualMouseButtonEvent;
81 import android.hardware.input.VirtualMouseConfig;
82 import android.hardware.input.VirtualMouseRelativeEvent;
83 import android.hardware.input.VirtualMouseScrollEvent;
84 import android.hardware.input.VirtualNavigationTouchpadConfig;
85 import android.hardware.input.VirtualRotaryEncoderConfig;
86 import android.hardware.input.VirtualRotaryEncoderScrollEvent;
87 import android.hardware.input.VirtualStylusButtonEvent;
88 import android.hardware.input.VirtualStylusConfig;
89 import android.hardware.input.VirtualStylusMotionEvent;
90 import android.hardware.input.VirtualTouchEvent;
91 import android.hardware.input.VirtualTouchscreenConfig;
92 import android.media.AudioManager;
93 import android.media.audiopolicy.AudioMix;
94 import android.os.Binder;
95 import android.os.Build;
96 import android.os.IBinder;
97 import android.os.LocaleList;
98 import android.os.Looper;
99 import android.os.PowerManager;
100 import android.os.RemoteException;
101 import android.os.ResultReceiver;
102 import android.os.SystemClock;
103 import android.os.UserHandle;
104 import android.os.UserManager;
105 import android.util.ArrayMap;
106 import android.util.ArraySet;
107 import android.util.IntArray;
108 import android.util.Slog;
109 import android.util.SparseArray;
110 import android.util.SparseIntArray;
111 import android.view.Display;
112 import android.view.WindowManager;
113 import android.widget.Toast;
114 import android.window.DisplayWindowPolicyController;
115 
116 import com.android.internal.annotations.GuardedBy;
117 import com.android.internal.annotations.VisibleForTesting;
118 import com.android.internal.app.BlockedAppStreamingActivity;
119 import com.android.modules.expresslog.Counter;
120 import com.android.server.LocalServices;
121 import com.android.server.companion.virtual.GenericWindowPolicyController.RunningAppsChangedListener;
122 import com.android.server.companion.virtual.audio.VirtualAudioController;
123 import com.android.server.companion.virtual.camera.VirtualCameraController;
124 import com.android.server.inputmethod.InputMethodManagerInternal;
125 
126 import dalvik.annotation.optimization.FastNative;
127 
128 import java.io.FileDescriptor;
129 import java.io.PrintWriter;
130 import java.util.List;
131 import java.util.Map;
132 import java.util.Objects;
133 import java.util.Set;
134 import java.util.function.Consumer;
135 
136 final class VirtualDeviceImpl extends IVirtualDevice.Stub
137         implements IBinder.DeathRecipient, RunningAppsChangedListener {
138 
139     private static final String TAG = "VirtualDeviceImpl";
140 
141     /**
142      * Do not show a toast on the virtual display when a secure surface is shown after
143      * {@link android.os.Build.VERSION_CODES#VANILLA_ICE_CREAM}. VDM clients should use
144      * {@link VirtualDeviceManager.ActivityListener#onSecureWindowShown} instead to provide
145      * a custom notification if desired.
146      */
147     @ChangeId
148     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM)
149     public static final long DO_NOT_SHOW_TOAST_WHEN_SECURE_SURFACE_SHOWN = 311101667L;
150 
151     private static final int DEFAULT_VIRTUAL_DISPLAY_FLAGS =
152             DisplayManager.VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED
153                     | DisplayManager.VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL
154                     | DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH
155                     | DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
156 
157     private static final String PERSISTENT_ID_PREFIX_CDM_ASSOCIATION = "companion:";
158 
159     private static final List<String> DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS = List.of(
160             AssociationRequest.DEVICE_PROFILE_APP_STREAMING);
161 
162     /**
163      * Timeout until {@link #launchPendingIntent} stops waiting for an activity to be launched.
164      */
165     private static final long PENDING_TRAMPOLINE_TIMEOUT_MS = 5000;
166 
167     /**
168      * Global lock for this Virtual Device.
169      *
170      * Never call outside this class while holding this lock. A number of other system services like
171      * WindowManager, DisplayManager, etc. call into this device to get device-specific information,
172      * while holding their own global locks.
173      *
174      * Making a call to another service while holding this lock creates lock order inversion and
175      * will potentially cause a deadlock.
176      */
177     private final Object mVirtualDeviceLock = new Object();
178 
179     private final int mBaseVirtualDisplayFlags;
180 
181     private final Context mContext;
182     private final AssociationInfo mAssociationInfo;
183     private final VirtualDeviceManagerService mService;
184     private final PendingTrampolineCallback mPendingTrampolineCallback;
185     private final int mOwnerUid;
186     private final VirtualDeviceLog mVirtualDeviceLog;
187     private final String mOwnerPackageName;
188     @NonNull
189     private final AttributionSource mAttributionSource;
190     private final int mDeviceId;
191     @Nullable
192     private final String mPersistentDeviceId;
193     private final InputController mInputController;
194     private final SensorController mSensorController;
195     private final CameraAccessController mCameraAccessController;
196     @Nullable // Null if virtual camera flag is off.
197     private final VirtualCameraController mVirtualCameraController;
198     private VirtualAudioController mVirtualAudioController;
199     private final IBinder mAppToken;
200     private final VirtualDeviceParams mParams;
201     @GuardedBy("mVirtualDeviceLock")
202     private final SparseIntArray mDevicePolicies;
203     @GuardedBy("mVirtualDeviceLock")
204     private final SparseArray<VirtualDisplayWrapper> mVirtualDisplays = new SparseArray<>();
205     private IVirtualDeviceActivityListener mActivityListener;
206     private GenericWindowPolicyController.ActivityListener mActivityListenerAdapter = null;
207     private IVirtualDeviceSoundEffectListener mSoundEffectListener;
208     private final DisplayManagerGlobal mDisplayManager;
209     private final DisplayManagerInternal mDisplayManagerInternal;
210     private final PowerManager mPowerManager;
211     @GuardedBy("mIntentInterceptors")
212     private final Map<IBinder, IntentFilter> mIntentInterceptors = new ArrayMap<>();
213     @NonNull
214     private final Consumer<ArraySet<Integer>> mRunningAppsChangedCallback;
215 
216     // The default setting for showing the pointer on new displays.
217     @GuardedBy("mVirtualDeviceLock")
218     private boolean mDefaultShowPointerIcon = true;
219     @GuardedBy("mVirtualDeviceLock")
220     @Nullable
221     private LocaleList mLocaleList = null;
222 
223     // Lock for power operations for this virtual device that allow calling PowerManager.
224     private final Object mPowerLock = new Object();
225     @GuardedBy("mPowerLock")
226     private boolean mLockdownActive = false;
227     @GuardedBy("mPowerLock")
228     private boolean mRequestedToBeAwake = true;
229 
230     @NonNull
231     private final VirtualDevice mPublicVirtualDeviceObject;
232 
233     @GuardedBy("mVirtualDeviceLock")
234     @NonNull
235     private final Set<ComponentName> mActivityPolicyExemptions;
236     @GuardedBy("mVirtualDeviceLock")
237     @NonNull
238     private final Set<String> mActivityPolicyPackageExemptions = new ArraySet<>();
239 
240     private class GwpcActivityListener implements GenericWindowPolicyController.ActivityListener {
241 
242         @Override
onTopActivityChanged(int displayId, @NonNull ComponentName topActivity, @UserIdInt int userId)243         public void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity,
244                 @UserIdInt int userId) {
245             try {
246                 mActivityListener.onTopActivityChanged(displayId, topActivity, userId);
247             } catch (RemoteException e) {
248                 Slog.w(TAG, "Unable to call mActivityListener for display: " + displayId, e);
249             }
250         }
251 
252         @Override
onDisplayEmpty(int displayId)253         public void onDisplayEmpty(int displayId) {
254             try {
255                 mActivityListener.onDisplayEmpty(displayId);
256             } catch (RemoteException e) {
257                 Slog.w(TAG, "Unable to call mActivityListener for display: " + displayId, e);
258             }
259         }
260 
261         @Override
onActivityLaunchBlocked(int displayId, @NonNull ActivityInfo activityInfo, @Nullable IntentSender intentSender)262         public void onActivityLaunchBlocked(int displayId, @NonNull ActivityInfo activityInfo,
263                 @Nullable IntentSender intentSender) {
264             Intent intent =
265                     BlockedAppStreamingActivity.createIntent(activityInfo, getDisplayName());
266             if (shouldShowBlockedActivityDialog(
267                     activityInfo.getComponentName(), intent.getComponent())) {
268                 mContext.startActivityAsUser(
269                         intent.addFlags(
270                                 Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK),
271                         ActivityOptions.makeBasic().setLaunchDisplayId(displayId).toBundle(),
272                         UserHandle.SYSTEM);
273             }
274 
275             if (Flags.activityControlApi()) {
276                 try {
277                     mActivityListener.onActivityLaunchBlocked(
278                             displayId,
279                             activityInfo.getComponentName(),
280                             UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid),
281                             intentSender);
282                 } catch (RemoteException e) {
283                     Slog.w(TAG, "Unable to call mActivityListener for display: " + displayId, e);
284                 }
285             }
286         }
287 
288         @Override
onSecureWindowShown(int displayId, @NonNull ActivityInfo activityInfo)289         public void onSecureWindowShown(int displayId, @NonNull ActivityInfo activityInfo) {
290             if (Flags.activityControlApi()) {
291                 try {
292                     mActivityListener.onSecureWindowShown(
293                             displayId,
294                             activityInfo.getComponentName(),
295                             UserHandle.getUserHandleForUid(activityInfo.applicationInfo.uid));
296                 } catch (RemoteException e) {
297                     Slog.w(TAG, "Unable to call mActivityListener for display: " + displayId, e);
298                 }
299 
300                 if (CompatChanges.isChangeEnabled(DO_NOT_SHOW_TOAST_WHEN_SECURE_SURFACE_SHOWN,
301                         mOwnerPackageName,  UserHandle.getUserHandleForUid(mOwnerUid))) {
302                     return;
303                 }
304             }
305 
306             // If a virtual display isn't secure, the screen can't be captured. Show a warning toast
307             // if the secure window is shown on a non-secure virtual display.
308             DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
309             Display display = displayManager.getDisplay(displayId);
310             if (display != null) {
311                 if ((display.getFlags() & Display.FLAG_SECURE) == 0) {
312                     showToastWhereUidIsRunning(activityInfo.applicationInfo.uid,
313                             com.android.internal.R.string.vdm_secure_window,
314                             Toast.LENGTH_LONG, mContext.getMainLooper());
315 
316                     Counter.logIncrementWithUid(
317                             "virtual_devices.value_secure_window_blocked_count",
318                             mAttributionSource.getUid());
319                 }
320             } else {
321                 Slog.e(TAG, "Calling onSecureWindowShown on a non existent/connected display: "
322                         + displayId);
323             }
324         }
325 
326         @Override
onSecureWindowHidden(int displayId)327         public void onSecureWindowHidden(int displayId) {
328             if (Flags.activityControlApi()) {
329                 try {
330                     mActivityListener.onSecureWindowHidden(displayId);
331                 } catch (RemoteException e) {
332                     Slog.w(TAG, "Unable to call mActivityListener for display: " + displayId, e);
333                 }
334             }
335         }
336 
337         /**
338          * Intercepts intent when matching any of the IntentFilter of any interceptor. Returns true
339          * if the intent matches any filter notifying the DisplayPolicyController to abort the
340          * activity launch to be replaced by the interception.
341          */
342         @Override
shouldInterceptIntent(@onNull Intent intent)343         public boolean shouldInterceptIntent(@NonNull Intent intent) {
344             synchronized (mIntentInterceptors) {
345                 boolean hasInterceptedIntent = false;
346                 for (Map.Entry<IBinder, IntentFilter> interceptor
347                         : mIntentInterceptors.entrySet()) {
348                     IntentFilter intentFilter = interceptor.getValue();
349                     // Explicitly match the actions because the intent filter will match any intent
350                     // without an explicit action. If the intent has no action, then require that
351                     // there are no actions specified in the filter either.
352                     boolean explicitActionMatch =
353                             intent.getAction() != null || intentFilter.countActions() == 0;
354                     if (explicitActionMatch && intentFilter.match(
355                             intent.getAction(), intent.getType(), intent.getScheme(),
356                             intent.getData(), intent.getCategories(), TAG) >= 0) {
357                         try {
358                             // For privacy reasons, only returning the intents action and data.
359                             // Any other required field will require a review.
360                             IVirtualDeviceIntentInterceptor.Stub.asInterface(interceptor.getKey())
361                                     .onIntentIntercepted(
362                                             new Intent(intent.getAction(), intent.getData()));
363                             hasInterceptedIntent = true;
364                         } catch (RemoteException e) {
365                             Slog.w(TAG, "Unable to call mActivityListener", e);
366                         }
367                     }
368                 }
369                 return hasInterceptedIntent;
370             }
371         }
372     }
373 
VirtualDeviceImpl( Context context, AssociationInfo associationInfo, VirtualDeviceManagerService service, VirtualDeviceLog virtualDeviceLog, IBinder token, AttributionSource attributionSource, int deviceId, CameraAccessController cameraAccessController, PendingTrampolineCallback pendingTrampolineCallback, IVirtualDeviceActivityListener activityListener, IVirtualDeviceSoundEffectListener soundEffectListener, Consumer<ArraySet<Integer>> runningAppsChangedCallback, VirtualDeviceParams params)374     VirtualDeviceImpl(
375             Context context,
376             AssociationInfo associationInfo,
377             VirtualDeviceManagerService service,
378             VirtualDeviceLog virtualDeviceLog,
379             IBinder token,
380             AttributionSource attributionSource,
381             int deviceId,
382             CameraAccessController cameraAccessController,
383             PendingTrampolineCallback pendingTrampolineCallback,
384             IVirtualDeviceActivityListener activityListener,
385             IVirtualDeviceSoundEffectListener soundEffectListener,
386             Consumer<ArraySet<Integer>> runningAppsChangedCallback,
387             VirtualDeviceParams params) {
388         this(
389                 context,
390                 associationInfo,
391                 service,
392                 virtualDeviceLog,
393                 token,
394                 attributionSource,
395                 deviceId,
396                 /* inputController= */ null,
397                 cameraAccessController,
398                 pendingTrampolineCallback,
399                 activityListener,
400                 soundEffectListener,
401                 runningAppsChangedCallback,
402                 params,
403                 DisplayManagerGlobal.getInstance(),
404                 isVirtualCameraEnabled()
405                         ? new VirtualCameraController(
406                                 params.getDevicePolicy(POLICY_TYPE_CAMERA), deviceId)
407                         : null);
408     }
409 
410     @VisibleForTesting
VirtualDeviceImpl( Context context, AssociationInfo associationInfo, VirtualDeviceManagerService service, VirtualDeviceLog virtualDeviceLog, IBinder token, AttributionSource attributionSource, int deviceId, InputController inputController, CameraAccessController cameraAccessController, PendingTrampolineCallback pendingTrampolineCallback, IVirtualDeviceActivityListener activityListener, IVirtualDeviceSoundEffectListener soundEffectListener, Consumer<ArraySet<Integer>> runningAppsChangedCallback, VirtualDeviceParams params, DisplayManagerGlobal displayManager, VirtualCameraController virtualCameraController)411     VirtualDeviceImpl(
412             Context context,
413             AssociationInfo associationInfo,
414             VirtualDeviceManagerService service,
415             VirtualDeviceLog virtualDeviceLog,
416             IBinder token,
417             AttributionSource attributionSource,
418             int deviceId,
419             InputController inputController,
420             CameraAccessController cameraAccessController,
421             PendingTrampolineCallback pendingTrampolineCallback,
422             IVirtualDeviceActivityListener activityListener,
423             IVirtualDeviceSoundEffectListener soundEffectListener,
424             Consumer<ArraySet<Integer>> runningAppsChangedCallback,
425             VirtualDeviceParams params,
426             DisplayManagerGlobal displayManager,
427             VirtualCameraController virtualCameraController) {
428         mVirtualDeviceLog = virtualDeviceLog;
429         mOwnerPackageName = attributionSource.getPackageName();
430         mAttributionSource = attributionSource;
431         UserHandle ownerUserHandle = UserHandle.getUserHandleForUid(attributionSource.getUid());
432         mContext = context.createContextAsUser(ownerUserHandle, 0);
433         mAssociationInfo = associationInfo;
434         mPersistentDeviceId = associationInfo == null
435                 ? null
436                 : createPersistentDeviceId(associationInfo.getId());
437         mService = service;
438         mPendingTrampolineCallback = pendingTrampolineCallback;
439         mActivityListener = activityListener;
440         mSoundEffectListener = soundEffectListener;
441         mRunningAppsChangedCallback = runningAppsChangedCallback;
442         mOwnerUid = attributionSource.getUid();
443         mDeviceId = deviceId;
444         mAppToken = token;
445         mParams = params;
446         mDevicePolicies = params.getDevicePolicies();
447         mDisplayManager = displayManager;
448         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
449         mPowerManager = context.getSystemService(PowerManager.class);
450 
451         if (mDevicePolicies.get(POLICY_TYPE_CLIPBOARD, DEVICE_POLICY_DEFAULT)
452                 != DEVICE_POLICY_DEFAULT) {
453             if (mContext.checkCallingOrSelfPermission(ADD_TRUSTED_DISPLAY)
454                     != PackageManager.PERMISSION_GRANTED) {
455                 throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
456                         + "set a custom clipboard policy.");
457             }
458         }
459 
460         int flags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
461         if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
462             if (mContext.checkCallingOrSelfPermission(ADD_ALWAYS_UNLOCKED_DISPLAY)
463                     != PackageManager.PERMISSION_GRANTED) {
464                 throw new SecurityException("Requires ADD_ALWAYS_UNLOCKED_DISPLAY permission to "
465                         + "create an always unlocked virtual device.");
466             }
467             flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
468         }
469         mBaseVirtualDisplayFlags = flags;
470 
471         if (inputController == null) {
472             mInputController = new InputController(
473                     context.getMainThreadHandler(),
474                     context.getSystemService(WindowManager.class), mAttributionSource);
475         } else {
476             mInputController = inputController;
477         }
478         mSensorController = new SensorController(this, mDeviceId, mAttributionSource,
479                 mParams.getVirtualSensorCallback(), mParams.getVirtualSensorConfigs());
480         mCameraAccessController = cameraAccessController;
481         if (mCameraAccessController != null) {
482             mCameraAccessController.startObservingIfNeeded();
483         }
484         mVirtualCameraController = virtualCameraController;
485         try {
486             token.linkToDeath(this, 0);
487         } catch (RemoteException e) {
488             throw e.rethrowFromSystemServer();
489         }
490         mVirtualDeviceLog.logCreated(deviceId, mOwnerUid);
491 
492         mPublicVirtualDeviceObject = new VirtualDevice(
493                 this, getDeviceId(), getPersistentDeviceId(), mParams.getName(), getDisplayName());
494 
495         mActivityPolicyExemptions = new ArraySet<>(
496                 mParams.getDevicePolicy(POLICY_TYPE_ACTIVITY) == DEVICE_POLICY_DEFAULT
497                         ? mParams.getBlockedActivities()
498                         : mParams.getAllowedActivities());
499 
500         if (mParams.getInputMethodComponent() != null) {
501             final String imeId = mParams.getInputMethodComponent().flattenToShortString();
502             Slog.d(TAG, "Setting custom input method " + imeId + " as default for virtual device "
503                     + deviceId);
504             InputMethodManagerInternal.get().setVirtualDeviceInputMethodForAllUsers(
505                     mDeviceId, imeId);
506         }
507     }
508 
onLockdownChanged(boolean lockdownActive)509     void onLockdownChanged(boolean lockdownActive) {
510         synchronized (mPowerLock) {
511             if (lockdownActive != mLockdownActive) {
512                 mLockdownActive = lockdownActive;
513                 if (mLockdownActive) {
514                     goToSleepInternal(PowerManager.GO_TO_SLEEP_REASON_DISPLAY_GROUPS_TURNED_OFF);
515                 } else if (mRequestedToBeAwake) {
516                     wakeUpInternal(PowerManager.WAKE_REASON_DISPLAY_GROUP_TURNED_ON,
517                             "android.server.companion.virtual:LOCKDOWN_ENDED");
518                 }
519             }
520         }
521     }
522 
523     @VisibleForTesting
getSensorControllerForTest()524     SensorController getSensorControllerForTest() {
525         return mSensorController;
526     }
527 
createPersistentDeviceId(int associationId)528     static String createPersistentDeviceId(int associationId) {
529         return PERSISTENT_ID_PREFIX_CDM_ASSOCIATION + associationId;
530     }
531 
532     /**
533      * Returns the flags that should be added to any virtual displays created on this virtual
534      * device.
535      */
getBaseVirtualDisplayFlags()536     int getBaseVirtualDisplayFlags() {
537         return mBaseVirtualDisplayFlags;
538     }
539 
540     /** Returns the camera access controller of this device. */
getCameraAccessController()541     CameraAccessController getCameraAccessController() {
542         return mCameraAccessController;
543     }
544 
545     /** Returns the device display name. */
getDisplayName()546     CharSequence getDisplayName() {
547         return mAssociationInfo == null ? mParams.getName() : mAssociationInfo.getDisplayName();
548     }
549 
getDeviceProfile()550     String getDeviceProfile() {
551         return mAssociationInfo == null ? null : mAssociationInfo.getDeviceProfile();
552     }
553 
554     /** Returns the public representation of the device. */
getPublicVirtualDeviceObject()555     VirtualDevice getPublicVirtualDeviceObject() {
556         return mPublicVirtualDeviceObject;
557     }
558 
559     /** Returns the locale of the device. */
getDeviceLocaleList()560     LocaleList getDeviceLocaleList() {
561         synchronized (mVirtualDeviceLock) {
562             return mLocaleList;
563         }
564     }
565 
566     /**
567      * Setter for listeners that live in the client process, namely in
568      * {@link android.companion.virtual.VirtualDeviceInternal}.
569      *
570      * This is needed for virtual devices that are created by the system, as the VirtualDeviceImpl
571      * object is created before the returned VirtualDeviceInternal one.
572      */
573     @Override // Binder call
setListeners(@onNull IVirtualDeviceActivityListener activityListener, @NonNull IVirtualDeviceSoundEffectListener soundEffectListener)574     public void setListeners(@NonNull IVirtualDeviceActivityListener activityListener,
575             @NonNull IVirtualDeviceSoundEffectListener soundEffectListener) {
576         mActivityListener = Objects.requireNonNull(activityListener);
577         mSoundEffectListener = Objects.requireNonNull(soundEffectListener);
578     }
579 
580     @Override  // Binder call
getDevicePolicy( @irtualDeviceParams.PolicyType int policyType)581     public @VirtualDeviceParams.DevicePolicy int getDevicePolicy(
582             @VirtualDeviceParams.PolicyType int policyType) {
583         synchronized (mVirtualDeviceLock) {
584             return mDevicePolicies.get(policyType, DEVICE_POLICY_DEFAULT);
585         }
586     }
587 
588     /** Returns device-specific audio session id for playback. */
getAudioPlaybackSessionId()589     public int getAudioPlaybackSessionId() {
590         return mParams.getAudioPlaybackSessionId();
591     }
592 
593     /** Returns device-specific audio session id for recording. */
getAudioRecordingSessionId()594     public int getAudioRecordingSessionId() {
595         return mParams.getAudioRecordingSessionId();
596     }
597 
598     /** Returns the unique device ID of this device. */
599     @Override // Binder call
getDeviceId()600     public int getDeviceId() {
601         return mDeviceId;
602     }
603 
604     /** Returns the unique device ID of this device. */
605     @Override // Binder call
getPersistentDeviceId()606     public @Nullable String getPersistentDeviceId() {
607         return mPersistentDeviceId;
608     }
609 
610     @Override // Binder call
getAssociationId()611     public int getAssociationId() {
612         return mAssociationInfo == null
613                 ? VirtualDeviceManagerService.CDM_ASSOCIATION_ID_NONE
614                 : mAssociationInfo.getId();
615     }
616 
617     @Override // Binder call
goToSleep()618     public void goToSleep() {
619         checkCallerIsDeviceOwner();
620         synchronized (mPowerLock) {
621             mRequestedToBeAwake = false;
622         }
623         final long ident = Binder.clearCallingIdentity();
624         try {
625             goToSleepInternal(PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON);
626         } finally {
627             Binder.restoreCallingIdentity(ident);
628         }
629     }
630 
631     @Override // Binder call
wakeUp()632     public void wakeUp() {
633         checkCallerIsDeviceOwner();
634         synchronized (mPowerLock) {
635             mRequestedToBeAwake = true;
636             if (mLockdownActive) {
637                 Slog.w(TAG, "Cannot wake up device during lockdown.");
638                 return;
639             }
640         }
641         final long ident = Binder.clearCallingIdentity();
642         try {
643             wakeUpInternal(PowerManager.WAKE_REASON_POWER_BUTTON,
644                     "android.server.companion.virtual:DEVICE_ON");
645         } finally {
646             Binder.restoreCallingIdentity(ident);
647         }
648     }
649 
650     @Override // Binder call
launchPendingIntent(int displayId, PendingIntent pendingIntent, ResultReceiver resultReceiver)651     public void launchPendingIntent(int displayId, PendingIntent pendingIntent,
652             ResultReceiver resultReceiver) {
653         checkCallerIsDeviceOwner();
654         Objects.requireNonNull(pendingIntent);
655         synchronized (mVirtualDeviceLock) {
656             checkDisplayOwnedByVirtualDeviceLocked(displayId);
657         }
658         if (pendingIntent.isActivity()) {
659             try {
660                 sendPendingIntent(displayId, pendingIntent);
661                 resultReceiver.send(VirtualDeviceManager.LAUNCH_SUCCESS, null);
662             } catch (PendingIntent.CanceledException e) {
663                 Slog.w(TAG, "Pending intent canceled", e);
664                 resultReceiver.send(
665                         VirtualDeviceManager.LAUNCH_FAILURE_PENDING_INTENT_CANCELED, null);
666             }
667         } else {
668             PendingTrampoline pendingTrampoline = new PendingTrampoline(pendingIntent,
669                     resultReceiver, displayId);
670             mPendingTrampolineCallback.startWaitingForPendingTrampoline(pendingTrampoline);
671             mContext.getMainThreadHandler().postDelayed(() -> {
672                 pendingTrampoline.mResultReceiver.send(
673                         VirtualDeviceManager.LAUNCH_FAILURE_NO_ACTIVITY, null);
674                 mPendingTrampolineCallback.stopWaitingForPendingTrampoline(pendingTrampoline);
675             }, PENDING_TRAMPOLINE_TIMEOUT_MS);
676             try {
677                 sendPendingIntent(displayId, pendingIntent);
678             } catch (PendingIntent.CanceledException e) {
679                 Slog.w(TAG, "Pending intent canceled", e);
680                 resultReceiver.send(
681                         VirtualDeviceManager.LAUNCH_FAILURE_PENDING_INTENT_CANCELED, null);
682                 mPendingTrampolineCallback.stopWaitingForPendingTrampoline(pendingTrampoline);
683             }
684         }
685     }
686 
687     @Override // Binder call
addActivityPolicyExemption(@onNull ActivityPolicyExemption exemption)688     public void addActivityPolicyExemption(@NonNull ActivityPolicyExemption exemption) {
689         checkCallerIsDeviceOwner();
690         final int displayId = exemption.getDisplayId();
691         if (exemption.getComponentName() == null || displayId != Display.INVALID_DISPLAY) {
692             if (!Flags.activityControlApi()) {
693                 return;
694             }
695         }
696         synchronized (mVirtualDeviceLock) {
697             if (displayId != Display.INVALID_DISPLAY) {
698                 checkDisplayOwnedByVirtualDeviceLocked(displayId);
699                 if (exemption.getComponentName() != null) {
700                     mVirtualDisplays.get(displayId).getWindowPolicyController()
701                             .addActivityPolicyExemption(exemption.getComponentName());
702                 } else if (exemption.getPackageName() != null) {
703                     mVirtualDisplays.get(displayId).getWindowPolicyController()
704                             .addActivityPolicyExemption(exemption.getPackageName());
705                 }
706             } else {
707                 if (exemption.getComponentName() != null
708                         && mActivityPolicyExemptions.add(exemption.getComponentName())) {
709                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
710                         mVirtualDisplays.valueAt(i).getWindowPolicyController()
711                                 .addActivityPolicyExemption(exemption.getComponentName());
712                     }
713                 } else if (exemption.getPackageName() != null
714                         && mActivityPolicyPackageExemptions.add(exemption.getPackageName())) {
715                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
716                         mVirtualDisplays.valueAt(i).getWindowPolicyController()
717                                 .addActivityPolicyExemption(exemption.getPackageName());
718                     }
719                 }
720             }
721         }
722     }
723 
724     @Override // Binder call
removeActivityPolicyExemption(@onNull ActivityPolicyExemption exemption)725     public void removeActivityPolicyExemption(@NonNull ActivityPolicyExemption exemption) {
726         checkCallerIsDeviceOwner();
727         final int displayId = exemption.getDisplayId();
728         if (exemption.getComponentName() == null || displayId != Display.INVALID_DISPLAY) {
729             if (!Flags.activityControlApi()) {
730                 return;
731             }
732         }
733         synchronized (mVirtualDeviceLock) {
734             if (displayId != Display.INVALID_DISPLAY) {
735                 checkDisplayOwnedByVirtualDeviceLocked(displayId);
736                 if (exemption.getComponentName() != null) {
737                     mVirtualDisplays.get(displayId).getWindowPolicyController()
738                             .removeActivityPolicyExemption(exemption.getComponentName());
739                 } else if (exemption.getPackageName() != null) {
740                     mVirtualDisplays.get(displayId).getWindowPolicyController()
741                             .removeActivityPolicyExemption(exemption.getPackageName());
742                 }
743             } else {
744                 if (exemption.getComponentName() != null
745                         && mActivityPolicyExemptions.remove(exemption.getComponentName())) {
746                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
747                         mVirtualDisplays.valueAt(i).getWindowPolicyController()
748                                 .removeActivityPolicyExemption(exemption.getComponentName());
749                     }
750                 } else if (exemption.getPackageName() != null
751                         && mActivityPolicyPackageExemptions.remove(exemption.getPackageName())) {
752                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
753                         mVirtualDisplays.valueAt(i).getWindowPolicyController()
754                                 .removeActivityPolicyExemption(exemption.getPackageName());
755                     }
756                 }
757             }
758         }
759     }
760 
sendPendingIntent(int displayId, PendingIntent pendingIntent)761     private void sendPendingIntent(int displayId, PendingIntent pendingIntent)
762             throws PendingIntent.CanceledException {
763         final ActivityOptions options = ActivityOptions.makeBasic().setLaunchDisplayId(displayId);
764         options.setPendingIntentBackgroundActivityStartMode(
765                 ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS);
766         pendingIntent.send(
767                 mContext,
768                 /* code= */ 0,
769                 /* intent= */ null,
770                 /* onFinished= */ null,
771                 /* handler= */ null,
772                 /* requiredPermission= */ null,
773                 options.toBundle());
774     }
775 
776     @Override // Binder call
close()777     public void close() {
778         // Remove about-to-be-closed virtual device from the service before butchering it.
779         if (!mService.removeVirtualDevice(mDeviceId)) {
780             // Device is already closed.
781             return;
782         }
783 
784         mVirtualDeviceLog.logClosed(mDeviceId, mOwnerUid);
785 
786         final long ident = Binder.clearCallingIdentity();
787         try {
788             VirtualDisplayWrapper[] virtualDisplaysToBeReleased;
789             synchronized (mVirtualDeviceLock) {
790                 if (mVirtualAudioController != null) {
791                     mVirtualAudioController.stopListening();
792                     mVirtualAudioController = null;
793                 }
794                 mLocaleList = null;
795                 virtualDisplaysToBeReleased = new VirtualDisplayWrapper[mVirtualDisplays.size()];
796                 for (int i = 0; i < mVirtualDisplays.size(); i++) {
797                     virtualDisplaysToBeReleased[i] = mVirtualDisplays.valueAt(i);
798                 }
799                 mVirtualDisplays.clear();
800             }
801             // Destroy the display outside locked section.
802             for (VirtualDisplayWrapper virtualDisplayWrapper : virtualDisplaysToBeReleased) {
803                 mDisplayManager.releaseVirtualDisplay(virtualDisplayWrapper.getToken());
804                 // The releaseVirtualDisplay call above won't trigger
805                 // VirtualDeviceImpl.onVirtualDisplayRemoved callback because we already removed the
806                 // virtual device from the service - we release the other display-tied resources
807                 // here with the guarantee it will be done exactly once.
808                 releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
809             }
810 
811             mAppToken.unlinkToDeath(this, 0);
812             if (mCameraAccessController != null) {
813                 mCameraAccessController.stopObservingIfNeeded();
814             }
815 
816             // Clear any previously set custom IME components.
817             if (mParams.getInputMethodComponent() != null) {
818                 InputMethodManagerInternal.get().setVirtualDeviceInputMethodForAllUsers(
819                         mDeviceId, null);
820             }
821 
822             mInputController.close();
823             mSensorController.close();
824         } finally {
825             Binder.restoreCallingIdentity(ident);
826         }
827         if (mVirtualCameraController != null) {
828             mVirtualCameraController.close();
829         }
830     }
831 
832     @Override
binderDied()833     public void binderDied() {
834         close();
835     }
836 
837     @Override
838     @RequiresPermission(android.Manifest.permission.CAMERA_INJECT_EXTERNAL_CAMERA)
onRunningAppsChanged(ArraySet<Integer> runningUids)839     public void onRunningAppsChanged(ArraySet<Integer> runningUids) {
840         if (mCameraAccessController != null) {
841             mCameraAccessController.blockCameraAccessIfNeeded(runningUids);
842         }
843         mRunningAppsChangedCallback.accept(runningUids);
844     }
845 
846     @VisibleForTesting
getVirtualAudioControllerForTesting()847     VirtualAudioController getVirtualAudioControllerForTesting() {
848         return mVirtualAudioController;
849     }
850 
851     @Override // Binder call
onAudioSessionStarting(int displayId, @NonNull IAudioRoutingCallback routingCallback, @Nullable IAudioConfigChangedCallback configChangedCallback)852     public void onAudioSessionStarting(int displayId,
853             @NonNull IAudioRoutingCallback routingCallback,
854             @Nullable IAudioConfigChangedCallback configChangedCallback) {
855         checkCallerIsDeviceOwner();
856         synchronized (mVirtualDeviceLock) {
857             checkDisplayOwnedByVirtualDeviceLocked(displayId);
858             if (mVirtualAudioController == null) {
859                 mVirtualAudioController = new VirtualAudioController(mContext, mAttributionSource);
860                 GenericWindowPolicyController gwpc =
861                         mVirtualDisplays.get(displayId).getWindowPolicyController();
862                 mVirtualAudioController.startListening(gwpc, routingCallback,
863                         configChangedCallback);
864             }
865         }
866     }
867 
868     @Override // Binder call
onAudioSessionEnded()869     public void onAudioSessionEnded() {
870         checkCallerIsDeviceOwner();
871         synchronized (mVirtualDeviceLock) {
872             if (mVirtualAudioController != null) {
873                 mVirtualAudioController.stopListening();
874                 mVirtualAudioController = null;
875             }
876         }
877     }
878 
879     @Override // Binder call
setDevicePolicy(@irtualDeviceParams.DynamicPolicyType int policyType, @VirtualDeviceParams.DevicePolicy int devicePolicy)880     public void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType,
881             @VirtualDeviceParams.DevicePolicy int devicePolicy) {
882         checkCallerIsDeviceOwner();
883 
884         switch (policyType) {
885             case POLICY_TYPE_RECENTS:
886                 synchronized (mVirtualDeviceLock) {
887                     mDevicePolicies.put(policyType, devicePolicy);
888                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
889                         VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
890                         if (wrapper.isTrusted()) {
891                             wrapper.getWindowPolicyController()
892                                     .setShowInHostDeviceRecents(
893                                             devicePolicy == DEVICE_POLICY_DEFAULT);
894                         }
895                     }
896                 }
897                 break;
898             case POLICY_TYPE_ACTIVITY:
899                 synchronized (mVirtualDeviceLock) {
900                     if (getDevicePolicy(policyType) != devicePolicy) {
901                         mActivityPolicyExemptions.clear();
902                         mActivityPolicyPackageExemptions.clear();
903                     }
904                     mDevicePolicies.put(policyType, devicePolicy);
905                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
906                         mVirtualDisplays.valueAt(i).getWindowPolicyController()
907                                 .setActivityLaunchDefaultAllowed(
908                                         devicePolicy == DEVICE_POLICY_DEFAULT);
909                     }
910                 }
911                 break;
912             case POLICY_TYPE_CLIPBOARD:
913                 if (devicePolicy == DEVICE_POLICY_CUSTOM
914                             && mContext.checkCallingOrSelfPermission(ADD_TRUSTED_DISPLAY)
915                             != PackageManager.PERMISSION_GRANTED) {
916                     throw new SecurityException("Requires ADD_TRUSTED_DISPLAY permission to "
917                             + "set a custom clipboard policy.");
918                 }
919                 synchronized (mVirtualDeviceLock) {
920                     for (int i = 0; i < mVirtualDisplays.size(); i++) {
921                         VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
922                         if (!wrapper.isTrusted() && !wrapper.isMirror()) {
923                             throw new SecurityException("All displays must be trusted for "
924                                     + "devices with custom clipboard policy.");
925                         }
926                     }
927                     mDevicePolicies.put(policyType, devicePolicy);
928                 }
929                 break;
930             case POLICY_TYPE_BLOCKED_ACTIVITY:
931                 if (Flags.activityControlApi()) {
932                     synchronized (mVirtualDeviceLock) {
933                         mDevicePolicies.put(policyType, devicePolicy);
934                     }
935                 }
936                 break;
937             default:
938                 throw new IllegalArgumentException("Device policy " + policyType
939                         + " cannot be changed at runtime. ");
940         }
941     }
942 
943     @Override // Binder call
setDevicePolicyForDisplay(int displayId, @VirtualDeviceParams.DynamicDisplayPolicyType int policyType, @VirtualDeviceParams.DevicePolicy int devicePolicy)944     public void setDevicePolicyForDisplay(int displayId,
945             @VirtualDeviceParams.DynamicDisplayPolicyType int policyType,
946             @VirtualDeviceParams.DevicePolicy int devicePolicy) {
947         checkCallerIsDeviceOwner();
948         if (!Flags.activityControlApi()) {
949             return;
950         }
951         synchronized (mVirtualDeviceLock) {
952             checkDisplayOwnedByVirtualDeviceLocked(displayId);
953             switch (policyType) {
954                 case POLICY_TYPE_RECENTS:
955                     VirtualDisplayWrapper wrapper = mVirtualDisplays.get(displayId);
956                     if (wrapper.isTrusted()) {
957                         wrapper.getWindowPolicyController()
958                                 .setShowInHostDeviceRecents(devicePolicy == DEVICE_POLICY_DEFAULT);
959                     }
960                     break;
961                 case POLICY_TYPE_ACTIVITY:
962                     mVirtualDisplays.get(displayId).getWindowPolicyController()
963                             .setActivityLaunchDefaultAllowed(devicePolicy == DEVICE_POLICY_DEFAULT);
964                     break;
965                 default:
966                     throw new IllegalArgumentException("Device policy " + policyType
967                             + " cannot be changed for a specific display. ");
968             }
969         }
970     }
971 
972     @Override // Binder call
createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken)973     public void createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken) {
974         checkCallerIsDeviceOwner();
975         Objects.requireNonNull(config);
976         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
977         final long ident = Binder.clearCallingIdentity();
978         try {
979             mInputController.createDpad(config.getInputDeviceName(), config.getVendorId(),
980                     config.getProductId(), deviceToken,
981                     getTargetDisplayIdForInput(config.getAssociatedDisplayId()));
982         } catch (InputController.DeviceCreationException e) {
983             throw new IllegalArgumentException(e);
984         } finally {
985             Binder.restoreCallingIdentity(ident);
986         }
987     }
988 
989     @Override // Binder call
createVirtualKeyboard(VirtualKeyboardConfig config, @NonNull IBinder deviceToken)990     public void createVirtualKeyboard(VirtualKeyboardConfig config, @NonNull IBinder deviceToken) {
991         checkCallerIsDeviceOwner();
992         Objects.requireNonNull(config);
993         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
994         final long ident = Binder.clearCallingIdentity();
995         try {
996             mInputController.createKeyboard(config.getInputDeviceName(), config.getVendorId(),
997                     config.getProductId(), deviceToken,
998                     getTargetDisplayIdForInput(config.getAssociatedDisplayId()),
999                     config.getLanguageTag(), config.getLayoutType());
1000             synchronized (mVirtualDeviceLock) {
1001                 mLocaleList = LocaleList.forLanguageTags(config.getLanguageTag());
1002             }
1003         } catch (InputController.DeviceCreationException e) {
1004             throw new IllegalArgumentException(e);
1005         } finally {
1006             Binder.restoreCallingIdentity(ident);
1007         }
1008     }
1009 
1010     @Override // Binder call
createVirtualMouse(VirtualMouseConfig config, @NonNull IBinder deviceToken)1011     public void createVirtualMouse(VirtualMouseConfig config, @NonNull IBinder deviceToken) {
1012         checkCallerIsDeviceOwner();
1013         Objects.requireNonNull(config);
1014         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
1015         final long ident = Binder.clearCallingIdentity();
1016         try {
1017             mInputController.createMouse(config.getInputDeviceName(), config.getVendorId(),
1018                     config.getProductId(), deviceToken, config.getAssociatedDisplayId());
1019         } catch (InputController.DeviceCreationException e) {
1020             throw new IllegalArgumentException(e);
1021         } finally {
1022             Binder.restoreCallingIdentity(ident);
1023         }
1024     }
1025 
1026     @Override // Binder call
createVirtualTouchscreen(VirtualTouchscreenConfig config, @NonNull IBinder deviceToken)1027     public void createVirtualTouchscreen(VirtualTouchscreenConfig config,
1028             @NonNull IBinder deviceToken) {
1029         checkCallerIsDeviceOwner();
1030         Objects.requireNonNull(config);
1031         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
1032         final long ident = Binder.clearCallingIdentity();
1033         try {
1034             mInputController.createTouchscreen(config.getInputDeviceName(), config.getVendorId(),
1035                     config.getProductId(), deviceToken, config.getAssociatedDisplayId(),
1036                     config.getHeight(), config.getWidth());
1037         } catch (InputController.DeviceCreationException e) {
1038             throw new IllegalArgumentException(e);
1039         } finally {
1040             Binder.restoreCallingIdentity(ident);
1041         }
1042     }
1043 
1044     @Override // Binder call
createVirtualNavigationTouchpad(VirtualNavigationTouchpadConfig config, @NonNull IBinder deviceToken)1045     public void createVirtualNavigationTouchpad(VirtualNavigationTouchpadConfig config,
1046             @NonNull IBinder deviceToken) {
1047         checkCallerIsDeviceOwner();
1048         Objects.requireNonNull(config);
1049         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
1050         final long ident = Binder.clearCallingIdentity();
1051         try {
1052             mInputController.createNavigationTouchpad(
1053                     config.getInputDeviceName(), config.getVendorId(),
1054                     config.getProductId(), deviceToken,
1055                     getTargetDisplayIdForInput(config.getAssociatedDisplayId()),
1056                     config.getHeight(), config.getWidth());
1057         } catch (InputController.DeviceCreationException e) {
1058             throw new IllegalArgumentException(e);
1059         } finally {
1060             Binder.restoreCallingIdentity(ident);
1061         }
1062     }
1063 
1064     @Override // Binder call
createVirtualStylus(@onNull VirtualStylusConfig config, @NonNull IBinder deviceToken)1065     public void createVirtualStylus(@NonNull VirtualStylusConfig config,
1066             @NonNull IBinder deviceToken) {
1067         checkCallerIsDeviceOwner();
1068         Objects.requireNonNull(config);
1069         Objects.requireNonNull(deviceToken);
1070         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
1071         final long ident = Binder.clearCallingIdentity();
1072         try {
1073             mInputController.createStylus(config.getInputDeviceName(), config.getVendorId(),
1074                     config.getProductId(), deviceToken, config.getAssociatedDisplayId(),
1075                     config.getHeight(), config.getWidth());
1076         } catch (InputController.DeviceCreationException e) {
1077             throw new IllegalArgumentException(e);
1078         } finally {
1079             Binder.restoreCallingIdentity(ident);
1080         }
1081     }
1082 
1083     @Override // Binder call
createVirtualRotaryEncoder(@onNull VirtualRotaryEncoderConfig config, @NonNull IBinder deviceToken)1084     public void createVirtualRotaryEncoder(@NonNull VirtualRotaryEncoderConfig config,
1085             @NonNull IBinder deviceToken) {
1086         checkCallerIsDeviceOwner();
1087         Objects.requireNonNull(config);
1088         Objects.requireNonNull(deviceToken);
1089         checkVirtualInputDeviceDisplayIdAssociation(config.getAssociatedDisplayId());
1090         final long ident = Binder.clearCallingIdentity();
1091         try {
1092             mInputController.createRotaryEncoder(config.getInputDeviceName(), config.getVendorId(),
1093                     config.getProductId(), deviceToken,
1094                     getTargetDisplayIdForInput(config.getAssociatedDisplayId()));
1095         } catch (InputController.DeviceCreationException e) {
1096             throw new IllegalArgumentException(e);
1097         } finally {
1098             Binder.restoreCallingIdentity(ident);
1099         }
1100     }
1101 
1102     @Override // Binder call
unregisterInputDevice(IBinder token)1103     public void unregisterInputDevice(IBinder token) {
1104         checkCallerIsDeviceOwner();
1105         final long ident = Binder.clearCallingIdentity();
1106         try {
1107             mInputController.unregisterInputDevice(token);
1108         } finally {
1109             Binder.restoreCallingIdentity(ident);
1110         }
1111     }
1112 
1113     @Override // Binder call
getInputDeviceId(IBinder token)1114     public int getInputDeviceId(IBinder token) {
1115         final long ident = Binder.clearCallingIdentity();
1116         try {
1117             return mInputController.getInputDeviceId(token);
1118         } finally {
1119             Binder.restoreCallingIdentity(ident);
1120         }
1121     }
1122 
1123 
1124     @Override // Binder call
sendDpadKeyEvent(IBinder token, VirtualKeyEvent event)1125     public boolean sendDpadKeyEvent(IBinder token, VirtualKeyEvent event) {
1126         checkCallerIsDeviceOwner();
1127         final long ident = Binder.clearCallingIdentity();
1128         try {
1129             return mInputController.sendDpadKeyEvent(token, event);
1130         } finally {
1131             Binder.restoreCallingIdentity(ident);
1132         }
1133     }
1134 
1135     @Override // Binder call
sendKeyEvent(IBinder token, VirtualKeyEvent event)1136     public boolean sendKeyEvent(IBinder token, VirtualKeyEvent event) {
1137         checkCallerIsDeviceOwner();
1138         final long ident = Binder.clearCallingIdentity();
1139         try {
1140             return mInputController.sendKeyEvent(token, event);
1141         } finally {
1142             Binder.restoreCallingIdentity(ident);
1143         }
1144     }
1145 
1146     @Override // Binder call
sendButtonEvent(IBinder token, VirtualMouseButtonEvent event)1147     public boolean sendButtonEvent(IBinder token, VirtualMouseButtonEvent event) {
1148         checkCallerIsDeviceOwner();
1149         final long ident = Binder.clearCallingIdentity();
1150         try {
1151             return mInputController.sendButtonEvent(token, event);
1152         } finally {
1153             Binder.restoreCallingIdentity(ident);
1154         }
1155     }
1156 
1157     @Override // Binder call
sendTouchEvent(IBinder token, VirtualTouchEvent event)1158     public boolean sendTouchEvent(IBinder token, VirtualTouchEvent event) {
1159         checkCallerIsDeviceOwner();
1160         final long ident = Binder.clearCallingIdentity();
1161         try {
1162             return mInputController.sendTouchEvent(token, event);
1163         } finally {
1164             Binder.restoreCallingIdentity(ident);
1165         }
1166     }
1167 
1168     @Override // Binder call
sendRelativeEvent(IBinder token, VirtualMouseRelativeEvent event)1169     public boolean sendRelativeEvent(IBinder token, VirtualMouseRelativeEvent event) {
1170         checkCallerIsDeviceOwner();
1171         final long ident = Binder.clearCallingIdentity();
1172         try {
1173             return mInputController.sendRelativeEvent(token, event);
1174         } finally {
1175             Binder.restoreCallingIdentity(ident);
1176         }
1177     }
1178 
1179     @Override // Binder call
sendScrollEvent(IBinder token, VirtualMouseScrollEvent event)1180     public boolean sendScrollEvent(IBinder token, VirtualMouseScrollEvent event) {
1181         checkCallerIsDeviceOwner();
1182         final long ident = Binder.clearCallingIdentity();
1183         try {
1184             return mInputController.sendScrollEvent(token, event);
1185         } finally {
1186             Binder.restoreCallingIdentity(ident);
1187         }
1188     }
1189 
1190     @Override // Binder call
getCursorPosition(IBinder token)1191     public PointF getCursorPosition(IBinder token) {
1192         final long ident = Binder.clearCallingIdentity();
1193         try {
1194             return mInputController.getCursorPosition(token);
1195         } finally {
1196             Binder.restoreCallingIdentity(ident);
1197         }
1198     }
1199 
1200     @Override // Binder call
sendStylusMotionEvent(@onNull IBinder token, @NonNull VirtualStylusMotionEvent event)1201     public boolean sendStylusMotionEvent(@NonNull IBinder token,
1202             @NonNull VirtualStylusMotionEvent event) {
1203         checkCallerIsDeviceOwner();
1204         Objects.requireNonNull(token);
1205         Objects.requireNonNull(event);
1206         final long ident = Binder.clearCallingIdentity();
1207         try {
1208             return mInputController.sendStylusMotionEvent(token, event);
1209         } finally {
1210             Binder.restoreCallingIdentity(ident);
1211         }
1212     }
1213 
1214     @Override // Binder call
sendStylusButtonEvent(@onNull IBinder token, @NonNull VirtualStylusButtonEvent event)1215     public boolean sendStylusButtonEvent(@NonNull IBinder token,
1216             @NonNull VirtualStylusButtonEvent event) {
1217         checkCallerIsDeviceOwner();
1218         Objects.requireNonNull(token);
1219         Objects.requireNonNull(event);
1220         final long ident = Binder.clearCallingIdentity();
1221         try {
1222             return mInputController.sendStylusButtonEvent(token, event);
1223         } finally {
1224             Binder.restoreCallingIdentity(ident);
1225         }
1226     }
1227 
1228     @Override // Binder call
sendRotaryEncoderScrollEvent(@onNull IBinder token, @NonNull VirtualRotaryEncoderScrollEvent event)1229     public boolean sendRotaryEncoderScrollEvent(@NonNull IBinder token,
1230             @NonNull VirtualRotaryEncoderScrollEvent event) {
1231         checkCallerIsDeviceOwner();
1232         final long ident = Binder.clearCallingIdentity();
1233         try {
1234             return mInputController.sendRotaryEncoderScrollEvent(token, event);
1235         } finally {
1236             Binder.restoreCallingIdentity(ident);
1237         }
1238     }
1239 
1240     @Override // Binder call
setShowPointerIcon(boolean showPointerIcon)1241     public void setShowPointerIcon(boolean showPointerIcon) {
1242         checkCallerIsDeviceOwner();
1243         final long ident = Binder.clearCallingIdentity();
1244         try {
1245             synchronized (mVirtualDeviceLock) {
1246                 mDefaultShowPointerIcon = showPointerIcon;
1247                 for (int i = 0; i < mVirtualDisplays.size(); i++) {
1248                     VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
1249                     if (wrapper.isTrusted() || wrapper.isMirror()) {
1250                         mInputController.setShowPointerIcon(
1251                                 mDefaultShowPointerIcon, mVirtualDisplays.keyAt(i));
1252                     }
1253                 }
1254             }
1255         } finally {
1256             Binder.restoreCallingIdentity(ident);
1257         }
1258     }
1259 
1260     @Override // Binder call
setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy)1261     public void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) {
1262         checkCallerIsDeviceOwner();
1263         synchronized (mVirtualDeviceLock) {
1264             checkDisplayOwnedByVirtualDeviceLocked(displayId);
1265         }
1266         final long ident = Binder.clearCallingIdentity();
1267         try {
1268             mInputController.setDisplayImePolicy(displayId, policy);
1269         } finally {
1270             Binder.restoreCallingIdentity(ident);
1271         }
1272     }
1273 
1274     @Override // Binder call
1275     @Nullable
getVirtualSensorList()1276     public List<VirtualSensor> getVirtualSensorList() {
1277         checkCallerIsDeviceOwner();
1278         return mSensorController.getSensorList();
1279     }
1280 
1281     @Nullable
getVirtualSensorByHandle(int handle)1282     VirtualSensor getVirtualSensorByHandle(int handle) {
1283         return mSensorController.getSensorByHandle(handle);
1284     }
1285 
1286     @Override // Binder call
sendSensorEvent(@onNull IBinder token, @NonNull VirtualSensorEvent event)1287     public boolean sendSensorEvent(@NonNull IBinder token, @NonNull VirtualSensorEvent event) {
1288         checkCallerIsDeviceOwner();
1289         final long ident = Binder.clearCallingIdentity();
1290         try {
1291             return mSensorController.sendSensorEvent(token, event);
1292         } finally {
1293             Binder.restoreCallingIdentity(ident);
1294         }
1295     }
1296 
1297     @Override // Binder call
sendSensorAdditionalInfo(@onNull IBinder token, @NonNull VirtualSensorAdditionalInfo info)1298     public boolean sendSensorAdditionalInfo(@NonNull IBinder token,
1299             @NonNull VirtualSensorAdditionalInfo info) {
1300         checkCallerIsDeviceOwner();
1301         final long ident = Binder.clearCallingIdentity();
1302         try {
1303             return mSensorController.sendSensorAdditionalInfo(token, info);
1304         } finally {
1305             Binder.restoreCallingIdentity(ident);
1306         }
1307     }
1308 
1309     @Override // Binder call
registerIntentInterceptor(IVirtualDeviceIntentInterceptor intentInterceptor, IntentFilter filter)1310     public void registerIntentInterceptor(IVirtualDeviceIntentInterceptor intentInterceptor,
1311             IntentFilter filter) {
1312         checkCallerIsDeviceOwner();
1313         Objects.requireNonNull(intentInterceptor);
1314         Objects.requireNonNull(filter);
1315         synchronized (mIntentInterceptors) {
1316             mIntentInterceptors.put(intentInterceptor.asBinder(), filter);
1317         }
1318     }
1319 
1320     @Override // Binder call
unregisterIntentInterceptor( @onNull IVirtualDeviceIntentInterceptor intentInterceptor)1321     public void unregisterIntentInterceptor(
1322             @NonNull IVirtualDeviceIntentInterceptor intentInterceptor) {
1323         checkCallerIsDeviceOwner();
1324         Objects.requireNonNull(intentInterceptor);
1325         synchronized (mIntentInterceptors) {
1326             mIntentInterceptors.remove(intentInterceptor.asBinder());
1327         }
1328     }
1329 
1330     @Override // Binder call
registerVirtualCamera(@onNull VirtualCameraConfig cameraConfig)1331     public void registerVirtualCamera(@NonNull VirtualCameraConfig cameraConfig)
1332             throws RemoteException {
1333         checkCallerIsDeviceOwner();
1334         Objects.requireNonNull(cameraConfig);
1335         if (mVirtualCameraController == null) {
1336             throw new UnsupportedOperationException("Virtual camera controller is not available");
1337         }
1338         mVirtualCameraController.registerCamera(cameraConfig, mAttributionSource);
1339     }
1340 
1341     @Override // Binder call
unregisterVirtualCamera(@onNull VirtualCameraConfig cameraConfig)1342     public void unregisterVirtualCamera(@NonNull VirtualCameraConfig cameraConfig)
1343             throws RemoteException {
1344         checkCallerIsDeviceOwner();
1345         Objects.requireNonNull(cameraConfig);
1346         if (mVirtualCameraController == null) {
1347             throw new UnsupportedOperationException("Virtual camera controller is not available");
1348         }
1349         mVirtualCameraController.unregisterCamera(cameraConfig);
1350     }
1351 
1352     @Override // Binder call
getVirtualCameraId(@onNull VirtualCameraConfig cameraConfig)1353     public String getVirtualCameraId(@NonNull VirtualCameraConfig cameraConfig)
1354             throws RemoteException {
1355         Objects.requireNonNull(cameraConfig);
1356         if (mVirtualCameraController == null) {
1357             throw new UnsupportedOperationException("Virtual camera controller is not available");
1358         }
1359         return mVirtualCameraController.getCameraId(cameraConfig);
1360     }
1361 
1362     @Override
hasCustomAudioInputSupport()1363     public boolean hasCustomAudioInputSupport() throws RemoteException {
1364         return hasCustomAudioInputSupportInternal();
1365     }
1366 
1367     @Override
canCreateMirrorDisplays()1368     public boolean canCreateMirrorDisplays() {
1369         return DEVICE_PROFILES_ALLOWING_MIRROR_DISPLAYS.contains(getDeviceProfile());
1370     }
1371 
hasCustomAudioInputSupportInternal()1372     private boolean hasCustomAudioInputSupportInternal() {
1373         if (!android.media.audiopolicy.Flags.audioMixTestApi()) {
1374             return false;
1375         }
1376         if (!android.media.audiopolicy.Flags.recordAudioDeviceAwarePermission()) {
1377             return false;
1378         }
1379 
1380         if (getDevicePolicy(POLICY_TYPE_AUDIO) == VirtualDeviceParams.DEVICE_POLICY_CUSTOM) {
1381             return true;
1382         }
1383         final long token = Binder.clearCallingIdentity();
1384         try {
1385             AudioManager audioManager = mContext.getSystemService(AudioManager.class);
1386             for (AudioMix mix : audioManager.getRegisteredPolicyMixes()) {
1387                 if (mix.matchesVirtualDeviceId(getDeviceId())
1388                         && mix.getMixType() == AudioMix.MIX_TYPE_RECORDERS) {
1389                     return true;
1390                 }
1391             }
1392         } finally {
1393             Binder.restoreCallingIdentity(token);
1394         }
1395         return false;
1396     }
1397 
1398     @Override
dump(FileDescriptor fd, PrintWriter fout, String[] args)1399     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
1400         String indent = "    ";
1401         fout.println("  VirtualDevice: ");
1402         fout.println(indent + "mDeviceId: " + mDeviceId);
1403         fout.println(indent + "mAssociationId: " + getAssociationId());
1404         fout.println(indent + "mOwnerPackageName: " + mOwnerPackageName);
1405         fout.println(indent + "mParams: ");
1406         mParams.dump(fout, indent + indent);
1407         fout.println(indent + "mVirtualDisplayIds: ");
1408         synchronized (mVirtualDeviceLock) {
1409             for (int i = 0; i < mVirtualDisplays.size(); i++) {
1410                 fout.println(indent + "  " + mVirtualDisplays.keyAt(i));
1411             }
1412             fout.println("    mDevicePolicies: " + mDevicePolicies);
1413             fout.println(indent + "mDefaultShowPointerIcon: " + mDefaultShowPointerIcon);
1414         }
1415         mInputController.dump(fout);
1416         mSensorController.dump(fout);
1417         if (mVirtualCameraController != null) {
1418             mVirtualCameraController.dump(fout, indent);
1419         }
1420         fout.println(
1421                 indent + "hasCustomAudioInputSupport: " + hasCustomAudioInputSupportInternal());
1422     }
1423 
1424     // For display mirroring, we want to dispatch all key events to the source (default) display,
1425     // as the virtual display doesn't have any focused windows. Hence, call this for
1426     // associating any input device to the source display if the input device emits any key events.
getTargetDisplayIdForInput(int displayId)1427     private int getTargetDisplayIdForInput(int displayId) {
1428         DisplayManagerInternal displayManager = LocalServices.getService(
1429                 DisplayManagerInternal.class);
1430         int mirroredDisplayId = displayManager.getDisplayIdToMirror(displayId);
1431         return mirroredDisplayId == Display.INVALID_DISPLAY ? displayId : mirroredDisplayId;
1432     }
1433 
createWindowPolicyController( @onNull Set<String> displayCategories)1434     private GenericWindowPolicyController createWindowPolicyController(
1435             @NonNull Set<String> displayCategories) {
1436         final boolean activityLaunchAllowedByDefault =
1437                 getDevicePolicy(POLICY_TYPE_ACTIVITY) == DEVICE_POLICY_DEFAULT;
1438         final boolean crossTaskNavigationAllowedByDefault =
1439                 mParams.getDefaultNavigationPolicy() == NAVIGATION_POLICY_DEFAULT_ALLOWED;
1440         final boolean showTasksInHostDeviceRecents =
1441                 getDevicePolicy(POLICY_TYPE_RECENTS) == DEVICE_POLICY_DEFAULT;
1442 
1443         synchronized (mVirtualDeviceLock) {
1444             if (mActivityListenerAdapter == null) {
1445                 mActivityListenerAdapter = new GwpcActivityListener();
1446             }
1447 
1448             return new GenericWindowPolicyController(
1449                     WindowManager.LayoutParams.FLAG_SECURE,
1450                     WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS,
1451                     mAttributionSource,
1452                     getAllowedUserHandles(),
1453                     activityLaunchAllowedByDefault,
1454                     mActivityPolicyExemptions,
1455                     mActivityPolicyPackageExemptions,
1456                     crossTaskNavigationAllowedByDefault,
1457                     /* crossTaskNavigationExemptions= */crossTaskNavigationAllowedByDefault
1458                             ? mParams.getBlockedCrossTaskNavigations()
1459                             : mParams.getAllowedCrossTaskNavigations(),
1460                     mActivityListenerAdapter,
1461                     displayCategories,
1462                     showTasksInHostDeviceRecents,
1463                     mParams.getHomeComponent());
1464         }
1465     }
1466 
1467     @Override // Binder call
createVirtualDisplay(@onNull VirtualDisplayConfig virtualDisplayConfig, @NonNull IVirtualDisplayCallback callback)1468     public int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig,
1469             @NonNull IVirtualDisplayCallback callback) {
1470         checkCallerIsDeviceOwner();
1471 
1472         final boolean isTrustedDisplay =
1473                 (virtualDisplayConfig.getFlags() & DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED)
1474                         == DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
1475         if (!isTrustedDisplay && getDevicePolicy(POLICY_TYPE_CLIPBOARD) != DEVICE_POLICY_DEFAULT) {
1476             throw new SecurityException(
1477                 "All displays must be trusted for devices with custom clipboard policy.");
1478         }
1479 
1480         GenericWindowPolicyController gwpc =
1481                 createWindowPolicyController(virtualDisplayConfig.getDisplayCategories());
1482 
1483         // Create the display outside of the lock to avoid deadlock. DisplayManagerService will
1484         // acquire the global WM lock while creating the display. At the same time, WM may query
1485         // VDM and this virtual device to get policies, display ownership, etc.
1486         int displayId = mDisplayManagerInternal.createVirtualDisplay(virtualDisplayConfig,
1487                     callback, this, gwpc, mOwnerPackageName);
1488         if (displayId == Display.INVALID_DISPLAY) {
1489             return displayId;
1490         }
1491 
1492         // DisplayManagerService will call onVirtualDisplayCreated() after the display is created,
1493         // while holding its own lock to ensure that this device knows about the display before any
1494         // other display listeners are notified about the display creation.
1495         VirtualDisplayWrapper displayWrapper;
1496         boolean showPointer;
1497         synchronized (mVirtualDeviceLock) {
1498             if (!mVirtualDisplays.contains(displayId)) {
1499                 throw new IllegalStateException("Virtual device was not notified about the "
1500                         + "creation of display with ID " + displayId);
1501             }
1502             displayWrapper = mVirtualDisplays.get(displayId);
1503             showPointer = mDefaultShowPointerIcon;
1504         }
1505         displayWrapper.acquireWakeLock();
1506         gwpc.registerRunningAppsChangedListener(/* listener= */ this);
1507 
1508         Binder.withCleanCallingIdentity(() -> {
1509             mInputController.setMouseScalingEnabled(false, displayId);
1510             mInputController.setDisplayEligibilityForPointerCapture(/* isEligible= */ false,
1511                     displayId);
1512             if (displayWrapper.isTrusted()) {
1513                 mInputController.setShowPointerIcon(showPointer, displayId);
1514                 mInputController.setDisplayImePolicy(displayId,
1515                         WindowManager.DISPLAY_IME_POLICY_LOCAL);
1516             } else {
1517                 gwpc.setShowInHostDeviceRecents(true);
1518             }
1519         });
1520 
1521         Counter.logIncrementWithUid(
1522                 "virtual_devices.value_virtual_display_created_count",
1523                 mAttributionSource.getUid());
1524         return displayId;
1525     }
1526 
createWakeLockForDisplay(int displayId)1527     private PowerManager.WakeLock createWakeLockForDisplay(int displayId) {
1528         if (Flags.deviceAwareDisplayPower()) {
1529             return null;
1530         }
1531         final long token = Binder.clearCallingIdentity();
1532         try {
1533             PowerManager powerManager = mContext.getSystemService(PowerManager.class);
1534             PowerManager.WakeLock wakeLock = powerManager.newWakeLock(
1535                     PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
1536                     TAG + ":" + displayId, displayId);
1537             return wakeLock;
1538         } finally {
1539             Binder.restoreCallingIdentity(token);
1540         }
1541     }
1542 
shouldShowBlockedActivityDialog(ComponentName blockedComponent, ComponentName blockedAppStreamingActivityComponent)1543     private boolean shouldShowBlockedActivityDialog(ComponentName blockedComponent,
1544             ComponentName blockedAppStreamingActivityComponent) {
1545         if (Objects.equals(blockedComponent, blockedAppStreamingActivityComponent)) {
1546             // Do not show the dialog if it was blocked for some reason already to avoid
1547             // infinite blocking loop.
1548             return false;
1549         }
1550         if (!Flags.activityControlApi()) {
1551             return true;
1552         }
1553         // Do not show the dialog if disabled by policy.
1554         return getDevicePolicy(POLICY_TYPE_BLOCKED_ACTIVITY) == DEVICE_POLICY_DEFAULT;
1555     }
1556 
getAllowedUserHandles()1557     private ArraySet<UserHandle> getAllowedUserHandles() {
1558         ArraySet<UserHandle> result = new ArraySet<>();
1559         final long token = Binder.clearCallingIdentity();
1560         try {
1561             DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
1562             UserManager userManager = mContext.getSystemService(UserManager.class);
1563             for (UserHandle profile : userManager.getAllProfiles()) {
1564                 int nearbyAppStreamingPolicy = dpm.getNearbyAppStreamingPolicy(
1565                         profile.getIdentifier());
1566                 if (nearbyAppStreamingPolicy == NEARBY_STREAMING_ENABLED
1567                         || nearbyAppStreamingPolicy == NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY) {
1568                     result.add(profile);
1569                 } else if (nearbyAppStreamingPolicy == NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY) {
1570                     if (mParams.getUsersWithMatchingAccounts().contains(profile)) {
1571                         result.add(profile);
1572                     }
1573                 }
1574             }
1575         } finally {
1576             Binder.restoreCallingIdentity(token);
1577         }
1578         return result;
1579     }
1580 
1581     /**
1582      * DisplayManagerService is notifying this virtual device about the display creation. This
1583      * should happen before the DisplayManagerInternal#createVirtualDisplay() call above
1584      * returns.
1585      * This is called while holding the DisplayManagerService lock, so no heavy-weight work must
1586      * be done here and especially *** no calls to WindowManager! ***
1587      */
onVirtualDisplayCreated(int displayId, IVirtualDisplayCallback callback, DisplayWindowPolicyController dwpc)1588     public void onVirtualDisplayCreated(int displayId, IVirtualDisplayCallback callback,
1589             DisplayWindowPolicyController dwpc) {
1590         final boolean isMirrorDisplay =
1591                 mDisplayManagerInternal.getDisplayIdToMirror(displayId) != Display.INVALID_DISPLAY;
1592         final boolean isTrustedDisplay =
1593                 (mDisplayManagerInternal.getDisplayInfo(displayId).flags & Display.FLAG_TRUSTED)
1594                         == Display.FLAG_TRUSTED;
1595 
1596         GenericWindowPolicyController gwpc = (GenericWindowPolicyController) dwpc;
1597         gwpc.setDisplayId(displayId, isMirrorDisplay);
1598         PowerManager.WakeLock wakeLock =
1599                 isTrustedDisplay ? createWakeLockForDisplay(displayId) : null;
1600         synchronized (mVirtualDeviceLock) {
1601             if (mVirtualDisplays.contains(displayId)) {
1602                 Slog.wtf(TAG, "Virtual device already has a virtual display with ID " + displayId);
1603                 return;
1604             }
1605             mVirtualDisplays.put(displayId, new VirtualDisplayWrapper(callback, gwpc, wakeLock,
1606                     isTrustedDisplay, isMirrorDisplay));
1607         }
1608     }
1609 
1610     /**
1611      * This is callback invoked by VirtualDeviceManagerService when VirtualDisplay was released
1612      * by DisplayManager (most probably caused by someone calling VirtualDisplay.close()).
1613      * At this point, the display is already released, but we still need to release the
1614      * corresponding wakeLock and unregister the RunningAppsChangedListener from corresponding
1615      * WindowPolicyController.
1616      *
1617      * Note that when the display is destroyed during VirtualDeviceImpl.close() call,
1618      * this callback won't be invoked because the display is removed from
1619      * VirtualDeviceManagerService before any resources are released.
1620      */
onVirtualDisplayRemoved(int displayId)1621     void onVirtualDisplayRemoved(int displayId) {
1622         VirtualDisplayWrapper virtualDisplayWrapper;
1623         synchronized (mVirtualDeviceLock) {
1624             virtualDisplayWrapper = mVirtualDisplays.removeReturnOld(displayId);
1625         }
1626 
1627         if (virtualDisplayWrapper == null) {
1628             Slog.w(TAG, "Virtual device " + mDeviceId + " doesn't have a virtual display with ID "
1629                     + displayId);
1630             return;
1631         }
1632 
1633         final long ident = Binder.clearCallingIdentity();
1634         try {
1635             releaseOwnedVirtualDisplayResources(virtualDisplayWrapper);
1636         } finally {
1637             Binder.restoreCallingIdentity(ident);
1638         }
1639     }
1640 
1641     @SuppressWarnings("AndroidFrameworkRequiresPermission")
checkVirtualInputDeviceDisplayIdAssociation(int displayId)1642     private void checkVirtualInputDeviceDisplayIdAssociation(int displayId) {
1643         // The INJECT_EVENTS permission allows for injecting input to any window / display.
1644         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.INJECT_EVENTS)
1645                     != PackageManager.PERMISSION_GRANTED) {
1646             synchronized (mVirtualDeviceLock) {
1647                 checkDisplayOwnedByVirtualDeviceLocked(displayId);
1648                 VirtualDisplayWrapper wrapper = mVirtualDisplays.get(displayId);
1649                 if (!wrapper.isTrusted() && !wrapper.isMirror()) {
1650                     throw new SecurityException(
1651                             "Cannot create input device associated with an untrusted display");
1652                 }
1653             }
1654         }
1655     }
1656 
1657     @GuardedBy("mVirtualDeviceLock")
checkDisplayOwnedByVirtualDeviceLocked(int displayId)1658     private void checkDisplayOwnedByVirtualDeviceLocked(int displayId) {
1659         if (!mVirtualDisplays.contains(displayId)) {
1660             throw new SecurityException(
1661                     "Invalid displayId: Display " + displayId
1662                             + " is not associated with this virtual device");
1663         }
1664     }
1665 
checkCallerIsDeviceOwner()1666     private void checkCallerIsDeviceOwner() {
1667         if (Binder.getCallingUid() != mOwnerUid) {
1668             throw new SecurityException(
1669                 "Caller is not the owner of this virtual device");
1670         }
1671     }
1672 
goToSleepInternal(@owerManager.GoToSleepReason int reason)1673     void goToSleepInternal(@PowerManager.GoToSleepReason int reason) {
1674         final long now = SystemClock.uptimeMillis();
1675         IntArray displayIds = new IntArray();
1676         synchronized (mVirtualDeviceLock) {
1677             for (int i = 0; i < mVirtualDisplays.size(); i++) {
1678                 VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
1679                 if (!wrapper.isTrusted() || wrapper.isMirror()) {
1680                     continue;
1681                 }
1682                 int displayId = mVirtualDisplays.keyAt(i);
1683                 displayIds.add(displayId);
1684             }
1685         }
1686         for (int i = 0; i < displayIds.size(); ++i) {
1687             mPowerManager.goToSleep(displayIds.get(i), now, reason, /* flags= */ 0);
1688         }
1689     }
1690 
wakeUpInternal(@owerManager.WakeReason int reason, String details)1691     void wakeUpInternal(@PowerManager.WakeReason int reason, String details) {
1692         final long now = SystemClock.uptimeMillis();
1693         IntArray displayIds = new IntArray();
1694         synchronized (mVirtualDeviceLock) {
1695             for (int i = 0; i < mVirtualDisplays.size(); i++) {
1696                 VirtualDisplayWrapper wrapper = mVirtualDisplays.valueAt(i);
1697                 if (!wrapper.isTrusted() || wrapper.isMirror()) {
1698                     continue;
1699                 }
1700                 int displayId = mVirtualDisplays.keyAt(i);
1701                 displayIds.add(displayId);
1702             }
1703         }
1704         for (int i = 0; i < displayIds.size(); ++i) {
1705             mPowerManager.wakeUp(now, reason, details, displayIds.get(i));
1706         }
1707     }
1708 
1709     /**
1710      * Release resources tied to virtual display owned by this VirtualDevice instance.
1711      *
1712      * Note that this method won't release the virtual display itself.
1713      *
1714      * @param virtualDisplayWrapper - VirtualDisplayWrapper to release resources for.
1715      */
releaseOwnedVirtualDisplayResources(VirtualDisplayWrapper virtualDisplayWrapper)1716     private void releaseOwnedVirtualDisplayResources(VirtualDisplayWrapper virtualDisplayWrapper) {
1717         virtualDisplayWrapper.releaseWakeLock();
1718         virtualDisplayWrapper.getWindowPolicyController().unregisterRunningAppsChangedListener(
1719                 this);
1720     }
1721 
getOwnerUid()1722     int getOwnerUid() {
1723         return mOwnerUid;
1724     }
1725 
getDimDurationMillis()1726     long getDimDurationMillis() {
1727         return mParams.getDimDuration().toMillis();
1728     }
1729 
getScreenOffTimeoutMillis()1730     long getScreenOffTimeoutMillis() {
1731         return mParams.getScreenOffTimeout().toMillis();
1732     }
1733 
1734     @Override  // Binder call
getDisplayIds()1735     public int[] getDisplayIds() {
1736         synchronized (mVirtualDeviceLock) {
1737             final int size = mVirtualDisplays.size();
1738             int[] displayIds = new int[size];
1739             for (int i = 0; i < size; i++) {
1740                 displayIds[i] = mVirtualDisplays.keyAt(i);
1741             }
1742             return displayIds;
1743         }
1744     }
1745 
1746     @VisibleForTesting
getDisplayWindowPolicyControllerForTest(int displayId)1747     GenericWindowPolicyController getDisplayWindowPolicyControllerForTest(int displayId) {
1748         VirtualDisplayWrapper virtualDisplayWrapper;
1749         synchronized (mVirtualDeviceLock) {
1750             virtualDisplayWrapper = mVirtualDisplays.get(displayId);
1751         }
1752         return virtualDisplayWrapper != null ? virtualDisplayWrapper.getWindowPolicyController()
1753                 : null;
1754     }
1755 
1756     /**
1757      * Returns true if an app with the given {@code uid} is currently running on this virtual
1758      * device.
1759      */
isAppRunningOnVirtualDevice(int uid)1760     boolean isAppRunningOnVirtualDevice(int uid) {
1761         synchronized (mVirtualDeviceLock) {
1762             for (int i = 0; i < mVirtualDisplays.size(); i++) {
1763                 if (mVirtualDisplays.valueAt(i).getWindowPolicyController().containsUid(uid)) {
1764                     return true;
1765                 }
1766             }
1767         }
1768         return false;
1769     }
1770 
1771     /**
1772      * Shows a toast on virtual displays owned by this device which have a given uid running.
1773      */
showToastWhereUidIsRunning(int uid, @StringRes int resId, @Toast.Duration int duration, Looper looper)1774     void showToastWhereUidIsRunning(int uid, @StringRes int resId, @Toast.Duration int duration,
1775             Looper looper) {
1776         showToastWhereUidIsRunning(uid, mContext.getString(resId), duration, looper);
1777     }
1778 
1779     /**
1780      * Shows a toast on virtual displays owned by this device which have a given uid running.
1781      */
showToastWhereUidIsRunning(int uid, String text, @Toast.Duration int duration, Looper looper)1782     void showToastWhereUidIsRunning(int uid, String text, @Toast.Duration int duration,
1783             Looper looper) {
1784         IntArray displayIdsForUid = getDisplayIdsWhereUidIsRunning(uid);
1785         if (displayIdsForUid.size() == 0) {
1786             return;
1787         }
1788         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
1789         for (int i = 0; i < displayIdsForUid.size(); i++) {
1790             Display display = displayManager.getDisplay(displayIdsForUid.get(i));
1791             if (display != null && display.isValid()) {
1792                 Toast.makeText(mContext.createDisplayContext(display), looper, text,
1793                         duration).show();
1794             }
1795         }
1796     }
1797 
getDisplayIdsWhereUidIsRunning(int uid)1798     private IntArray getDisplayIdsWhereUidIsRunning(int uid) {
1799         IntArray displayIdsForUid = new IntArray();
1800         synchronized (mVirtualDeviceLock) {
1801             for (int i = 0; i < mVirtualDisplays.size(); i++) {
1802                 if (mVirtualDisplays.valueAt(i).getWindowPolicyController().containsUid(uid)) {
1803                     displayIdsForUid.add(mVirtualDisplays.keyAt(i));
1804                 }
1805             }
1806         }
1807         return displayIdsForUid;
1808     }
1809 
isDisplayOwnedByVirtualDevice(int displayId)1810     boolean isDisplayOwnedByVirtualDevice(int displayId) {
1811         synchronized (mVirtualDeviceLock) {
1812             return mVirtualDisplays.contains(displayId);
1813         }
1814     }
1815 
isInputDeviceOwnedByVirtualDevice(int inputDeviceId)1816     boolean isInputDeviceOwnedByVirtualDevice(int inputDeviceId) {
1817         return mInputController.getInputDeviceDescriptors().values().stream().anyMatch(
1818                 inputDeviceDescriptor -> inputDeviceDescriptor.getInputDeviceId() == inputDeviceId);
1819     }
1820 
playSoundEffect(int effectType)1821     void playSoundEffect(int effectType) {
1822         try {
1823             mSoundEffectListener.onPlaySoundEffect(effectType);
1824         } catch (RemoteException exception) {
1825             Slog.w(TAG, "Unable to invoke sound effect listener", exception);
1826         }
1827     }
1828 
1829     interface PendingTrampolineCallback {
1830         /**
1831          * Called when the callback should start waiting for the given pending trampoline.
1832          * Implementations should try to listen for activity starts associated with the given
1833          * {@code pendingTrampoline}, and launch the activity on the display with
1834          * {@link PendingTrampoline#mDisplayId}.
1835          */
startWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline)1836         void startWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline);
1837 
1838         /**
1839          * Called when the callback should stop waiting for the given pending trampoline. This can
1840          * happen, for example, when the pending intent failed to send.
1841          */
stopWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline)1842         void stopWaitingForPendingTrampoline(PendingTrampoline pendingTrampoline);
1843     }
1844 
1845     /**
1846      * A data class storing a pending trampoline this device is expecting.
1847      */
1848     static class PendingTrampoline {
1849 
1850         /**
1851          * The original pending intent sent, for which a trampoline activity launch is expected.
1852          */
1853         final PendingIntent mPendingIntent;
1854 
1855         /**
1856          * The result receiver associated with this pending call. {@link Activity#RESULT_OK} will
1857          * be sent to the receiver if the trampoline activity was captured successfully.
1858          * {@link Activity#RESULT_CANCELED} is sent otherwise.
1859          */
1860         final ResultReceiver mResultReceiver;
1861 
1862         /**
1863          * The display ID to send the captured trampoline activity launch to.
1864          */
1865         final int mDisplayId;
1866 
PendingTrampoline(PendingIntent pendingIntent, ResultReceiver resultReceiver, int displayId)1867         private PendingTrampoline(PendingIntent pendingIntent, ResultReceiver resultReceiver,
1868                 int displayId) {
1869             mPendingIntent = pendingIntent;
1870             mResultReceiver = resultReceiver;
1871             mDisplayId = displayId;
1872         }
1873 
1874         @Override
toString()1875         public String toString() {
1876             return "PendingTrampoline{"
1877                     + "pendingIntent=" + mPendingIntent
1878                     + ", resultReceiver=" + mResultReceiver
1879                     + ", displayId=" + mDisplayId + "}";
1880         }
1881     }
1882 
1883     /** Data class wrapping resources tied to single virtual display. */
1884     private static final class VirtualDisplayWrapper {
1885         private final IVirtualDisplayCallback mToken;
1886         private final GenericWindowPolicyController mWindowPolicyController;
1887         private final PowerManager.WakeLock mWakeLock;
1888         private final boolean mIsTrusted;
1889         private final boolean mIsMirror;
1890 
VirtualDisplayWrapper(@onNull IVirtualDisplayCallback token, @NonNull GenericWindowPolicyController windowPolicyController, @Nullable PowerManager.WakeLock wakeLock, boolean isTrusted, boolean isMirror)1891         VirtualDisplayWrapper(@NonNull IVirtualDisplayCallback token,
1892                 @NonNull GenericWindowPolicyController windowPolicyController,
1893                 @Nullable PowerManager.WakeLock wakeLock, boolean isTrusted, boolean isMirror) {
1894             mToken = Objects.requireNonNull(token);
1895             mWindowPolicyController = Objects.requireNonNull(windowPolicyController);
1896             mWakeLock = wakeLock;
1897             mIsTrusted = isTrusted;
1898             mIsMirror = isMirror;
1899         }
1900 
getWindowPolicyController()1901         GenericWindowPolicyController getWindowPolicyController() {
1902             return mWindowPolicyController;
1903         }
1904 
acquireWakeLock()1905         void acquireWakeLock() {
1906             if (mWakeLock != null && !mWakeLock.isHeld()) {
1907                 mWakeLock.acquire();
1908             }
1909         }
1910 
releaseWakeLock()1911         void releaseWakeLock() {
1912             if (mWakeLock != null && mWakeLock.isHeld()) {
1913                 mWakeLock.release();
1914             }
1915         }
1916 
isTrusted()1917         boolean isTrusted() {
1918             return mIsTrusted;
1919         }
1920 
isMirror()1921         boolean isMirror() {
1922             return mIsMirror;
1923         }
1924 
getToken()1925         IVirtualDisplayCallback getToken() {
1926             return mToken;
1927         }
1928     }
1929 
isVirtualCameraEnabled()1930     private static boolean isVirtualCameraEnabled() {
1931         return nativeVirtualCameraServiceBuildFlagEnabled();
1932     }
1933 
1934     // Returns true if virtual_camera service is enabled in this build.
1935     @FastNative
nativeVirtualCameraServiceBuildFlagEnabled()1936     private static native boolean nativeVirtualCameraServiceBuildFlagEnabled();
1937 }
1938