1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.companion.virtual; 18 19 import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; 20 21 import android.annotation.CallbackExecutor; 22 import android.annotation.FlaggedApi; 23 import android.annotation.IntDef; 24 import android.annotation.IntRange; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.annotation.RequiresPermission; 28 import android.annotation.SdkConstant; 29 import android.annotation.SuppressLint; 30 import android.annotation.SystemApi; 31 import android.annotation.SystemService; 32 import android.annotation.TestApi; 33 import android.annotation.UserIdInt; 34 import android.app.PendingIntent; 35 import android.companion.AssociationInfo; 36 import android.companion.virtual.audio.VirtualAudioDevice; 37 import android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback; 38 import android.companion.virtual.camera.VirtualCamera; 39 import android.companion.virtual.camera.VirtualCameraConfig; 40 import android.companion.virtual.sensor.VirtualSensor; 41 import android.companion.virtualdevice.flags.Flags; 42 import android.content.ComponentName; 43 import android.content.Context; 44 import android.content.Intent; 45 import android.content.IntentFilter; 46 import android.content.IntentSender; 47 import android.graphics.Point; 48 import android.hardware.display.DisplayManager; 49 import android.hardware.display.DisplayManager.VirtualDisplayFlag; 50 import android.hardware.display.VirtualDisplay; 51 import android.hardware.display.VirtualDisplayConfig; 52 import android.hardware.input.VirtualDpad; 53 import android.hardware.input.VirtualDpadConfig; 54 import android.hardware.input.VirtualKeyboard; 55 import android.hardware.input.VirtualKeyboardConfig; 56 import android.hardware.input.VirtualMouse; 57 import android.hardware.input.VirtualMouseConfig; 58 import android.hardware.input.VirtualNavigationTouchpad; 59 import android.hardware.input.VirtualNavigationTouchpadConfig; 60 import android.hardware.input.VirtualRotaryEncoder; 61 import android.hardware.input.VirtualRotaryEncoderConfig; 62 import android.hardware.input.VirtualStylus; 63 import android.hardware.input.VirtualStylusConfig; 64 import android.hardware.input.VirtualTouchscreen; 65 import android.hardware.input.VirtualTouchscreenConfig; 66 import android.media.AudioManager; 67 import android.os.Binder; 68 import android.os.Looper; 69 import android.os.RemoteException; 70 import android.os.UserHandle; 71 import android.util.ArraySet; 72 import android.util.Log; 73 import android.view.Display; 74 import android.view.Surface; 75 import android.view.WindowManager; 76 77 import com.android.internal.annotations.GuardedBy; 78 79 import java.lang.annotation.ElementType; 80 import java.lang.annotation.Retention; 81 import java.lang.annotation.RetentionPolicy; 82 import java.lang.annotation.Target; 83 import java.util.ArrayList; 84 import java.util.Collections; 85 import java.util.Iterator; 86 import java.util.List; 87 import java.util.Objects; 88 import java.util.Set; 89 import java.util.concurrent.Executor; 90 import java.util.function.IntConsumer; 91 92 /** 93 * System level service for creation and management of virtual devices. 94 * 95 * <p>VirtualDeviceManager enables interactive sharing of capabilities between the host Android 96 * device and a remote device. 97 * 98 * <p class="note">Not to be confused with the Android Studio's Virtual Device Manager, which allows 99 * for device emulation. 100 */ 101 @SystemService(Context.VIRTUAL_DEVICE_SERVICE) 102 public final class VirtualDeviceManager { 103 104 private static final String TAG = "VirtualDeviceManager"; 105 106 /** 107 * Broadcast Action: A Virtual Device was removed. 108 * 109 * <p class="note">This is a protected intent that can only be sent by the system.</p> 110 * 111 * @hide 112 */ 113 @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) 114 public static final String ACTION_VIRTUAL_DEVICE_REMOVED = 115 "android.companion.virtual.action.VIRTUAL_DEVICE_REMOVED"; 116 117 /** 118 * Int intent extra to be used with {@link #ACTION_VIRTUAL_DEVICE_REMOVED}. 119 * Contains the identifier of the virtual device, which was removed. 120 * 121 * @hide 122 */ 123 public static final String EXTRA_VIRTUAL_DEVICE_ID = 124 "android.companion.virtual.extra.VIRTUAL_DEVICE_ID"; 125 126 /** @hide */ 127 @Retention(RetentionPolicy.SOURCE) 128 @IntDef( 129 prefix = "LAUNCH_", 130 value = { 131 LAUNCH_SUCCESS, 132 LAUNCH_FAILURE_PENDING_INTENT_CANCELED, 133 LAUNCH_FAILURE_NO_ACTIVITY}) 134 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 135 public @interface PendingIntentLaunchStatus {} 136 137 /** 138 * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch was 139 * successful. 140 * 141 * @hide 142 */ 143 @SystemApi 144 public static final int LAUNCH_SUCCESS = 0; 145 146 /** 147 * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch failed 148 * because the pending intent was canceled. 149 * 150 * @hide 151 */ 152 @SystemApi 153 public static final int LAUNCH_FAILURE_PENDING_INTENT_CANCELED = 1; 154 155 /** 156 * Status for {@link VirtualDevice#launchPendingIntent}, indicating that the launch failed 157 * because no activity starts were detected as a result of calling the pending intent. 158 * 159 * @hide 160 */ 161 @SystemApi 162 public static final int LAUNCH_FAILURE_NO_ACTIVITY = 2; 163 164 /** 165 * Persistent device identifier corresponding to the default device. 166 * 167 * @see Context#DEVICE_ID_DEFAULT 168 * @see VirtualDevice#getPersistentDeviceId() 169 * 170 * @hide 171 */ 172 @SystemApi 173 public static final String PERSISTENT_DEVICE_ID_DEFAULT = 174 "default:" + Context.DEVICE_ID_DEFAULT; 175 176 private final IVirtualDeviceManager mService; 177 private final Context mContext; 178 179 @GuardedBy("mVirtualDeviceListeners") 180 private final List<VirtualDeviceListenerDelegate> mVirtualDeviceListeners = new ArrayList<>(); 181 182 /** @hide */ VirtualDeviceManager( @ullable IVirtualDeviceManager service, @NonNull Context context)183 public VirtualDeviceManager( 184 @Nullable IVirtualDeviceManager service, @NonNull Context context) { 185 mService = service; 186 mContext = context; 187 } 188 189 /** 190 * Creates a virtual device where applications can launch and receive input events injected by 191 * the creator. 192 * 193 * <p>The {@link android.Manifest.permission#CREATE_VIRTUAL_DEVICE} permission is required to 194 * create virtual devices, which is only available to system apps holding specific roles. 195 * 196 * @param associationId The association ID as returned by {@link AssociationInfo#getId()} from 197 * Companion Device Manager. Virtual devices must have a corresponding association with CDM in 198 * order to be created. 199 * @param params The parameters for creating virtual devices. See {@link VirtualDeviceParams} 200 * for the available options. 201 * @return The created virtual device. 202 * 203 * @hide 204 */ 205 @SystemApi 206 @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) 207 @NonNull createVirtualDevice( int associationId, @NonNull VirtualDeviceParams params)208 public VirtualDevice createVirtualDevice( 209 int associationId, 210 @NonNull VirtualDeviceParams params) { 211 Objects.requireNonNull(params, "params must not be null"); 212 try { 213 return new VirtualDevice(mService, mContext, associationId, params); 214 } catch (RemoteException e) { 215 throw e.rethrowFromSystemServer(); 216 } 217 } 218 219 /** 220 * Returns the details of all available virtual devices. 221 * 222 * <p>The returned objects are read-only representations that expose the properties of all 223 * existing virtual devices.</p> 224 * 225 * <p>Note that if a virtual device is closed and becomes invalid, the returned objects will 226 * not be updated and may contain stale values. Use a {@link VirtualDeviceListener} for real 227 * time updates of the availability of virtual devices.</p> 228 */ 229 @NonNull getVirtualDevices()230 public List<android.companion.virtual.VirtualDevice> getVirtualDevices() { 231 if (mService == null) { 232 Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service."); 233 return new ArrayList<>(); 234 } 235 try { 236 return mService.getVirtualDevices(); 237 } catch (RemoteException e) { 238 throw e.rethrowFromSystemServer(); 239 } 240 } 241 242 /** 243 * Returns the details of the virtual device with the given ID, if any. 244 * 245 * <p>The returned object is a read-only representation of the virtual device that expose its 246 * properties.</p> 247 * 248 * <p>Note that if the virtual device is closed and becomes invalid, the returned object will 249 * not be updated and may contain stale values. Use a {@link VirtualDeviceListener} for real 250 * time updates of the availability of virtual devices.</p> 251 * 252 * @return the virtual device with the requested ID, or {@code null} if no such device exists or 253 * it has already been closed. 254 */ 255 @Nullable getVirtualDevice(int deviceId)256 public android.companion.virtual.VirtualDevice getVirtualDevice(int deviceId) { 257 if (mService == null) { 258 Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service."); 259 return null; 260 } 261 if (deviceId == Context.DEVICE_ID_INVALID || deviceId == Context.DEVICE_ID_DEFAULT) { 262 return null; // Don't even bother making a Binder call. 263 } 264 try { 265 return mService.getVirtualDevice(deviceId); 266 } catch (RemoteException e) { 267 throw e.rethrowFromSystemServer(); 268 } 269 } 270 271 /** 272 * Registers a virtual device listener to receive notifications when virtual devices are created 273 * or closed. 274 * 275 * @param executor The executor where the listener is executed on. 276 * @param listener The listener to add. 277 * @see #unregisterVirtualDeviceListener 278 */ registerVirtualDeviceListener( @onNull @allbackExecutor Executor executor, @NonNull VirtualDeviceListener listener)279 public void registerVirtualDeviceListener( 280 @NonNull @CallbackExecutor Executor executor, 281 @NonNull VirtualDeviceListener listener) { 282 if (mService == null) { 283 Log.w(TAG, "Failed to register listener; no virtual device manager service."); 284 return; 285 } 286 final VirtualDeviceListenerDelegate delegate = 287 new VirtualDeviceListenerDelegate(Objects.requireNonNull(executor), 288 Objects.requireNonNull(listener)); 289 synchronized (mVirtualDeviceListeners) { 290 try { 291 mService.registerVirtualDeviceListener(delegate); 292 } catch (RemoteException e) { 293 throw e.rethrowFromSystemServer(); 294 } 295 mVirtualDeviceListeners.add(delegate); 296 } 297 } 298 299 /** 300 * Unregisters a virtual device listener previously registered with 301 * {@link #registerVirtualDeviceListener}. 302 * 303 * @param listener The listener to unregister. 304 * @see #registerVirtualDeviceListener 305 */ unregisterVirtualDeviceListener(@onNull VirtualDeviceListener listener)306 public void unregisterVirtualDeviceListener(@NonNull VirtualDeviceListener listener) { 307 if (mService == null) { 308 Log.w(TAG, "Failed to unregister listener; no virtual device manager service."); 309 return; 310 } 311 Objects.requireNonNull(listener); 312 synchronized (mVirtualDeviceListeners) { 313 final Iterator<VirtualDeviceListenerDelegate> it = mVirtualDeviceListeners.iterator(); 314 while (it.hasNext()) { 315 final VirtualDeviceListenerDelegate delegate = it.next(); 316 if (delegate.mListener == listener) { 317 try { 318 mService.unregisterVirtualDeviceListener(delegate); 319 } catch (RemoteException e) { 320 throw e.rethrowFromSystemServer(); 321 } 322 it.remove(); 323 } 324 } 325 } 326 } 327 328 /** 329 * Returns the device policy for the given virtual device and policy type. 330 * 331 * <p>In case the virtual device identifier is not valid, or there's no explicitly specified 332 * policy for that device and policy type, then 333 * {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT} is returned. 334 * 335 * @hide 336 */ 337 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 338 @TestApi getDevicePolicy( int deviceId, @VirtualDeviceParams.PolicyType int policyType)339 public @VirtualDeviceParams.DevicePolicy int getDevicePolicy( 340 int deviceId, @VirtualDeviceParams.PolicyType int policyType) { 341 if (deviceId == Context.DEVICE_ID_DEFAULT) { 342 // Avoid unnecessary binder call, for default device, policy will be always default. 343 return VirtualDeviceParams.DEVICE_POLICY_DEFAULT; 344 } 345 if (mService == null) { 346 Log.w(TAG, "Failed to retrieve device policy; no virtual device manager service."); 347 return VirtualDeviceParams.DEVICE_POLICY_DEFAULT; 348 } 349 try { 350 return mService.getDevicePolicy(deviceId, policyType); 351 } catch (RemoteException e) { 352 throw e.rethrowFromSystemServer(); 353 } 354 } 355 356 /** 357 * Returns the ID of the device which owns the display with the given ID. 358 * 359 * @hide 360 */ 361 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 362 @TestApi getDeviceIdForDisplayId(int displayId)363 public int getDeviceIdForDisplayId(int displayId) { 364 if (displayId == Display.DEFAULT_DISPLAY || displayId == Display.INVALID_DISPLAY) { 365 // Avoid unnecessary binder call for default / invalid display id. 366 return Context.DEVICE_ID_DEFAULT; 367 } 368 if (mService == null) { 369 Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service."); 370 return Context.DEVICE_ID_DEFAULT; 371 } 372 try { 373 return mService.getDeviceIdForDisplayId(displayId); 374 } catch (RemoteException e) { 375 throw e.rethrowFromSystemServer(); 376 } 377 } 378 379 /** 380 * Get the display name for a given persistent device ID. 381 * 382 * <p>This will work even if currently there is no valid virtual device with the given 383 * persistent ID, as long as such a device has been created or can be created.</p> 384 * 385 * @return the display name associated with the given persistent device ID, or {@code null} if 386 * the persistent ID is invalid or does not correspond to a virtual device. 387 * 388 * @see VirtualDevice#getPersistentDeviceId() 389 * @hide 390 */ 391 @SystemApi 392 @Nullable getDisplayNameForPersistentDeviceId(@onNull String persistentDeviceId)393 public CharSequence getDisplayNameForPersistentDeviceId(@NonNull String persistentDeviceId) { 394 if (mService == null) { 395 Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service."); 396 return null; 397 } 398 try { 399 return mService.getDisplayNameForPersistentDeviceId( 400 Objects.requireNonNull(persistentDeviceId)); 401 } catch (RemoteException e) { 402 throw e.rethrowFromSystemServer(); 403 } 404 } 405 406 /** 407 * Returns all current persistent device IDs, including the ones for which no virtual device 408 * exists, as long as one may have existed or can be created. 409 * 410 * @see VirtualDevice#getPersistentDeviceId() 411 * @hide 412 */ 413 @SystemApi 414 @NonNull getAllPersistentDeviceIds()415 public Set<String> getAllPersistentDeviceIds() { 416 if (mService == null) { 417 Log.w(TAG, "Failed to retrieve persistent ids; no virtual device manager service."); 418 return Collections.emptySet(); 419 } 420 try { 421 return new ArraySet<>(mService.getAllPersistentDeviceIds()); 422 } catch (RemoteException e) { 423 throw e.rethrowFromSystemServer(); 424 } 425 } 426 427 /** 428 * Checks whether the passed {@code deviceId} is a valid virtual device ID or not. 429 * {@link Context#DEVICE_ID_DEFAULT} is not valid as it is the ID of the default 430 * device which is not a virtual device. {@code deviceId} must correspond to a virtual device 431 * created by {@link VirtualDeviceManager#createVirtualDevice(int, VirtualDeviceParams)}. 432 * 433 * @hide 434 */ isValidVirtualDeviceId(int deviceId)435 public boolean isValidVirtualDeviceId(int deviceId) { 436 if (mService == null) { 437 Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service."); 438 return false; 439 } 440 try { 441 return mService.isValidVirtualDeviceId(deviceId); 442 } catch (RemoteException e) { 443 throw e.rethrowFromSystemServer(); 444 } 445 } 446 447 /** 448 * Returns device-specific audio session id for audio playback. 449 * 450 * @param deviceId - id of the virtual audio device 451 * @return Device specific session id to be used for audio playback (see 452 * {@link AudioManager#generateAudioSessionId}) if virtual device has 453 * {@link VirtualDeviceParams#POLICY_TYPE_AUDIO} set to 454 * {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM} and Virtual Audio Device 455 * is configured in context-aware mode. Otherwise 456 * {@link AudioManager#AUDIO_SESSION_ID_GENERATE} constant is returned. 457 * 458 * @hide 459 */ 460 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 461 @TestApi getAudioPlaybackSessionId(int deviceId)462 public int getAudioPlaybackSessionId(int deviceId) { 463 if (mService == null) { 464 return AUDIO_SESSION_ID_GENERATE; 465 } 466 try { 467 return mService.getAudioPlaybackSessionId(deviceId); 468 } catch (RemoteException e) { 469 throw e.rethrowFromSystemServer(); 470 } 471 } 472 473 /** 474 * Returns device-specific audio session id for audio recording. 475 * 476 * @param deviceId - id of the virtual audio device 477 * @return Device specific session id to be used for audio recording (see 478 * {@link AudioManager#generateAudioSessionId}) if virtual device has 479 * {@link VirtualDeviceParams#POLICY_TYPE_AUDIO} set to 480 * {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM} and Virtual Audio Device 481 * is configured in context-aware mode. Otherwise 482 * {@link AudioManager#AUDIO_SESSION_ID_GENERATE} constant is returned. 483 * 484 * @hide 485 */ 486 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 487 @TestApi getAudioRecordingSessionId(int deviceId)488 public int getAudioRecordingSessionId(int deviceId) { 489 if (mService == null) { 490 return AUDIO_SESSION_ID_GENERATE; 491 } 492 try { 493 return mService.getAudioRecordingSessionId(deviceId); 494 } catch (RemoteException e) { 495 throw e.rethrowFromSystemServer(); 496 } 497 } 498 499 /** 500 * Requests sound effect to be played on virtual device. 501 * 502 * @see AudioManager#playSoundEffect(int) 503 * 504 * @param deviceId - id of the virtual audio device 505 * @param effectType the type of sound effect 506 * 507 * @hide 508 */ 509 @SuppressLint("UnflaggedApi") // @TestApi without associated feature. 510 @TestApi playSoundEffect(int deviceId, @AudioManager.SystemSoundEffect int effectType)511 public void playSoundEffect(int deviceId, @AudioManager.SystemSoundEffect int effectType) { 512 if (mService == null) { 513 Log.w(TAG, "Failed to dispatch sound effect; no virtual device manager service."); 514 return; 515 } 516 try { 517 mService.playSoundEffect(deviceId, effectType); 518 } catch (RemoteException e) { 519 throw e.rethrowFromSystemServer(); 520 } 521 } 522 523 /** 524 * Returns whether the given display is an auto-mirror display owned by a virtual device. 525 * 526 * @hide 527 */ 528 @TestApi isVirtualDeviceOwnedMirrorDisplay(int displayId)529 public boolean isVirtualDeviceOwnedMirrorDisplay(int displayId) { 530 if (mService == null) { 531 Log.w(TAG, "Failed to retrieve virtual devices; no virtual device manager service."); 532 return false; 533 } 534 try { 535 return mService.isVirtualDeviceOwnedMirrorDisplay(displayId); 536 } catch (RemoteException e) { 537 throw e.rethrowFromSystemServer(); 538 } 539 } 540 541 /** 542 * A representation of a virtual device. 543 * 544 * <p>A virtual device can have its own virtual displays, audio input/output, sensors, etc. 545 * The creator of a virtual device can take the output from the virtual display and stream it 546 * over to another device, and inject input and sensor events that are received from the remote 547 * device. 548 * 549 * <p>This object is only used by the virtual device creator and allows them to manage the 550 * device's behavior, peripherals, and the user interaction with that device. 551 * 552 * <p class="note">Not to be confused with {@link android.companion.virtual.VirtualDevice}, 553 * which is a read-only representation exposing the properties of an existing virtual device. 554 * 555 * @hide 556 */ 557 @SystemApi 558 public static class VirtualDevice implements AutoCloseable { 559 560 private final VirtualDeviceInternal mVirtualDeviceInternal; 561 562 @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) VirtualDevice( IVirtualDeviceManager service, Context context, int associationId, VirtualDeviceParams params)563 private VirtualDevice( 564 IVirtualDeviceManager service, 565 Context context, 566 int associationId, 567 VirtualDeviceParams params) throws RemoteException { 568 mVirtualDeviceInternal = 569 new VirtualDeviceInternal(service, context, associationId, params); 570 } 571 572 /** @hide */ VirtualDevice(Context context, IVirtualDevice virtualDevice)573 public VirtualDevice(Context context, IVirtualDevice virtualDevice) { 574 mVirtualDeviceInternal = new VirtualDeviceInternal(context, virtualDevice); 575 } 576 577 /** 578 * Returns the unique ID of this virtual device. 579 */ getDeviceId()580 public int getDeviceId() { 581 return mVirtualDeviceInternal.getDeviceId(); 582 } 583 584 /** 585 * Returns the persistent ID of this virtual device. 586 */ getPersistentDeviceId()587 public @Nullable String getPersistentDeviceId() { 588 return mVirtualDeviceInternal.getPersistentDeviceId(); 589 } 590 591 /** 592 * Returns a new context bound to this device. 593 * 594 * <p>This is a convenience method equivalent to calling 595 * {@link Context#createDeviceContext(int)} with the id of this device. 596 */ createContext()597 public @NonNull Context createContext() { 598 return mVirtualDeviceInternal.createContext(); 599 } 600 601 /** 602 * Returns this device's sensors. 603 * 604 * @see VirtualDeviceParams.Builder#addVirtualSensorConfig 605 * 606 * @return A list of all sensors for this device, or an empty list if no sensors exist. 607 */ 608 @NonNull getVirtualSensorList()609 public List<VirtualSensor> getVirtualSensorList() { 610 return mVirtualDeviceInternal.getVirtualSensorList(); 611 } 612 613 /** 614 * Forces all trusted non-mirror displays of the virtual device to turn off. 615 * 616 * <p>After this action, if all displays across all devices, including the default one, are 617 * off, then the physical device will be put to sleep. If the displays of this virtual 618 * device are already off, then nothing will happen.</p> 619 * 620 * <p>Overrides all the wake locks that are held. This is equivalent to pressing a "virtual 621 * power key" to turn off the screen.</p> 622 * 623 * @see #wakeUp() 624 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 625 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY 626 */ 627 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) goToSleep()628 public void goToSleep() { 629 mVirtualDeviceInternal.goToSleep(); 630 } 631 632 /** 633 * Forces all trusted non-mirror displays of the virtual device to turn on. 634 * 635 * <p>If the displays of this virtual device are turned off, then they will be turned on. 636 * Additionally, if the device is asleep it will be awoken. If the displays of this virtual 637 * device are already on, then nothing will happen.</p> 638 * 639 * <p>This is equivalent to pressing a "virtual power key" to turn on the screen.</p> 640 * 641 * @see #goToSleep() 642 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 643 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY 644 */ 645 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) wakeUp()646 public void wakeUp() { 647 mVirtualDeviceInternal.wakeUp(); 648 } 649 650 /** 651 * Launches a given pending intent on the give display ID. 652 * 653 * @param displayId The display to launch the pending intent on. This display must be 654 * created from this virtual device. 655 * @param pendingIntent The pending intent to be launched. If the intent is an activity 656 * intent, the activity will be started on the virtual display using 657 * {@link android.app.ActivityOptions#setLaunchDisplayId}. If the intent is a service or 658 * broadcast intent, an attempt will be made to catch activities started as a result of 659 * sending the pending intent and move them to the given display. When it completes, 660 * {@code listener} will be called with the status of whether the launch attempt is 661 * successful or not. 662 * @param executor The executor to run {@code launchCallback} on. 663 * @param listener Listener that is called when the pending intent launching is complete. 664 * The argument is {@link #LAUNCH_SUCCESS} if the launch successfully started an activity 665 * on the virtual display, or one of the {@code LAUNCH_FAILED} status explaining why it 666 * failed. 667 */ launchPendingIntent( int displayId, @NonNull PendingIntent pendingIntent, @NonNull Executor executor, @NonNull IntConsumer listener)668 public void launchPendingIntent( 669 int displayId, 670 @NonNull PendingIntent pendingIntent, 671 @NonNull Executor executor, 672 @NonNull IntConsumer listener) { 673 Objects.requireNonNull(pendingIntent, "pendingIntent must not be null"); 674 Objects.requireNonNull(executor, "executor must not be null"); 675 Objects.requireNonNull(listener, "listener must not be null"); 676 mVirtualDeviceInternal.launchPendingIntent( 677 displayId, pendingIntent, executor, listener); 678 } 679 680 /** 681 * Creates a virtual display for this virtual device. All displays created on the same 682 * device belongs to the same display group. 683 * 684 * @param width The width of the virtual display in pixels, must be greater than 0. 685 * @param height The height of the virtual display in pixels, must be greater than 0. 686 * @param densityDpi The density of the virtual display in dpi, must be greater than 0. 687 * @param surface The surface to which the content of the virtual display should 688 * be rendered, or null if there is none initially. The surface can also be set later 689 * using {@link VirtualDisplay#setSurface(Surface)}. 690 * @param flags A combination of virtual display flags accepted by 691 * {@link DisplayManager#createVirtualDisplay}. In addition, the following flags are 692 * automatically set for all virtual devices: 693 * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC} and 694 * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}. 695 * @param executor The executor on which {@code callback} will be invoked. This is ignored 696 * if {@code callback} is {@code null}. If {@code callback} is specified, this executor 697 * must not be null. 698 * @param callback Callback to call when the state of the {@link VirtualDisplay} changes 699 * @return The newly created virtual display, or {@code null} if the application could 700 * not create the virtual display. 701 * 702 * @see DisplayManager#createVirtualDisplay 703 * 704 * @deprecated use {@link #createVirtualDisplay(VirtualDisplayConfig, Executor, 705 * VirtualDisplay.Callback)} 706 */ 707 @Deprecated 708 @Nullable createVirtualDisplay( @ntRangefrom = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, @Nullable Surface surface, @VirtualDisplayFlag int flags, @Nullable @CallbackExecutor Executor executor, @Nullable VirtualDisplay.Callback callback)709 public VirtualDisplay createVirtualDisplay( 710 @IntRange(from = 1) int width, 711 @IntRange(from = 1) int height, 712 @IntRange(from = 1) int densityDpi, 713 @Nullable Surface surface, 714 @VirtualDisplayFlag int flags, 715 @Nullable @CallbackExecutor Executor executor, 716 @Nullable VirtualDisplay.Callback callback) { 717 // Currently this just uses the device ID, which means all of the virtual displays 718 // created using the same virtual device will have the same name if they use this 719 // deprecated API. The name should only be used for informational purposes, and not for 720 // identifying the display in code. 721 String virtualDisplayName = "VirtualDevice_" + getDeviceId(); 722 VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder( 723 virtualDisplayName, width, height, densityDpi) 724 .setFlags(flags); 725 if (surface != null) { 726 builder.setSurface(surface); 727 } 728 return mVirtualDeviceInternal.createVirtualDisplay(builder.build(), executor, callback); 729 } 730 731 /** 732 * Creates a virtual display for this virtual device. All displays created on the same 733 * device belongs to the same display group. 734 * 735 * @param config The configuration of the display. 736 * @param executor The executor on which {@code callback} will be invoked. This is ignored 737 * if {@code callback} is {@code null}. If {@code callback} is specified, this executor 738 * must not be null. 739 * @param callback Callback to call when the state of the {@link VirtualDisplay} changes 740 * @return The newly created virtual display, or {@code null} if the application could 741 * not create the virtual display. 742 * 743 * @see DisplayManager#createVirtualDisplay 744 */ 745 @Nullable createVirtualDisplay( @onNull VirtualDisplayConfig config, @Nullable @CallbackExecutor Executor executor, @Nullable VirtualDisplay.Callback callback)746 public VirtualDisplay createVirtualDisplay( 747 @NonNull VirtualDisplayConfig config, 748 @Nullable @CallbackExecutor Executor executor, 749 @Nullable VirtualDisplay.Callback callback) { 750 Objects.requireNonNull(config, "config must not be null"); 751 return mVirtualDeviceInternal.createVirtualDisplay(config, executor, callback); 752 } 753 754 /** 755 * Closes the virtual device, stopping and tearing down any virtual displays, associated 756 * virtual audio device, and event injection that's currently in progress. 757 */ close()758 public void close() { 759 mVirtualDeviceInternal.close(); 760 } 761 762 /** 763 * Specifies a policy for this virtual device. 764 * 765 * <p>Policies define the system behavior that may be specific for this virtual device. The 766 * given policy must be able to be changed dynamically during the lifetime of the device. 767 * 768 * @param policyType the type of policy, i.e. which behavior to specify a policy for. 769 * @param devicePolicy the value of the policy, i.e. how to interpret the device behavior. 770 * @throws IllegalArgumentException if the policy cannot be changed at runtime. 771 * 772 * @see VirtualDeviceParams#POLICY_TYPE_RECENTS 773 * @see VirtualDeviceParams#POLICY_TYPE_ACTIVITY 774 */ setDevicePolicy(@irtualDeviceParams.DynamicPolicyType int policyType, @VirtualDeviceParams.DevicePolicy int devicePolicy)775 public void setDevicePolicy(@VirtualDeviceParams.DynamicPolicyType int policyType, 776 @VirtualDeviceParams.DevicePolicy int devicePolicy) { 777 mVirtualDeviceInternal.setDevicePolicy(policyType, devicePolicy); 778 } 779 780 /** 781 * Specifies a component name to be exempt from the current activity launch policy. 782 * 783 * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity 784 * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}), 785 * then the specified component will be blocked from launching. 786 * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches 787 * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then the 788 * specified component will be allowed to launch.</p> 789 * 790 * <p>Note that changing the activity launch policy will clear current set of exempt 791 * components.</p> 792 * 793 * @see #removeActivityPolicyExemption(ComponentName) 794 * @see #setDevicePolicy 795 */ addActivityPolicyExemption(@onNull ComponentName componentName)796 public void addActivityPolicyExemption(@NonNull ComponentName componentName) { 797 addActivityPolicyExemption(new ActivityPolicyExemption.Builder() 798 .setComponentName(componentName) 799 .build()); 800 } 801 802 /** 803 * Makes the specified component name to adhere to the default activity launch policy. 804 * 805 * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity 806 * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}), 807 * then the specified component will be allowed to launch. 808 * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches 809 * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then the 810 * specified component will be blocked from launching.</p> 811 * 812 * <p>Note that changing the activity launch policy will clear current set of exempt 813 * components.</p> 814 * 815 * @see #addActivityPolicyExemption(ComponentName) 816 * @see #setDevicePolicy 817 */ removeActivityPolicyExemption(@onNull ComponentName componentName)818 public void removeActivityPolicyExemption(@NonNull ComponentName componentName) { 819 removeActivityPolicyExemption(new ActivityPolicyExemption.Builder() 820 .setComponentName(componentName) 821 .build()); 822 } 823 824 /** 825 * Specifies an exemption from the current activity launch policy. 826 * 827 * <p>If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} allows activity 828 * launches by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_DEFAULT}), 829 * then all exempt activities be blocked from launching. 830 * If the current {@link VirtualDeviceParams#POLICY_TYPE_ACTIVITY} blocks activity launches 831 * by default, (i.e. it is {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM}), then all 832 * exempt activities will be allowed to launch.</p> 833 * 834 * <p>Note that changing the activity launch policy will clear current set of exempt 835 * packages.</p> 836 * <p>Any change to the exemptions will only be applied for new activity launches.</p> 837 * 838 * @see #removeActivityPolicyExemption(ActivityPolicyExemption) 839 * @see #setDevicePolicy 840 */ 841 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) addActivityPolicyExemption(@onNull ActivityPolicyExemption exemption)842 public void addActivityPolicyExemption(@NonNull ActivityPolicyExemption exemption) { 843 mVirtualDeviceInternal.addActivityPolicyExemption(Objects.requireNonNull(exemption)); 844 } 845 846 /** 847 * Removes an exemption from the current activity launch policy. 848 * 849 * <p>Note that changing the activity launch policy will clear current set of exempt 850 * packages.</p> 851 * <p>Any change to the exemptions will only be applied for new activity launches.</p> 852 * 853 * @see #addActivityPolicyExemption(ActivityPolicyExemption) 854 * @see #setDevicePolicy 855 */ 856 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) removeActivityPolicyExemption(@onNull ActivityPolicyExemption exemption)857 public void removeActivityPolicyExemption(@NonNull ActivityPolicyExemption exemption) { 858 mVirtualDeviceInternal.removeActivityPolicyExemption(Objects.requireNonNull(exemption)); 859 } 860 861 /** 862 * Specifies a policy for this virtual device to be applied on the given virtual display. 863 * <p> 864 * Any policy specified for a particular display takes precedence over the policy specified 865 * for the device itself. 866 * </p> 867 * 868 * @param policyType the type of policy, i.e. which behavior to specify a policy for. 869 * @param devicePolicy the value of the policy, i.e. how to interpret the device behavior. 870 * @param displayId the ID of the display, for which to apply the policy. 871 * @throws IllegalArgumentException if the specified policy cannot be changed per 872 * display or if the specified display does not belong to the virtual device. 873 * 874 * @see #setDevicePolicy(int, int) 875 * @see VirtualDeviceParams#POLICY_TYPE_RECENTS 876 * @see VirtualDeviceParams#POLICY_TYPE_ACTIVITY 877 */ 878 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) setDevicePolicy( @irtualDeviceParams.DynamicDisplayPolicyType int policyType, @VirtualDeviceParams.DevicePolicy int devicePolicy, int displayId)879 public void setDevicePolicy( 880 @VirtualDeviceParams.DynamicDisplayPolicyType int policyType, 881 @VirtualDeviceParams.DevicePolicy int devicePolicy, 882 int displayId) { 883 mVirtualDeviceInternal.setDevicePolicyForDisplay(displayId, policyType, devicePolicy); 884 } 885 886 /** 887 * Creates a virtual dpad. 888 * 889 * @param config the configurations of the virtual dpad. 890 */ 891 @NonNull createVirtualDpad(@onNull VirtualDpadConfig config)892 public VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) { 893 Objects.requireNonNull(config, "config must not be null"); 894 return mVirtualDeviceInternal.createVirtualDpad(config); 895 } 896 897 /** 898 * Creates a virtual keyboard. 899 * 900 * @param config the configurations of the virtual keyboard. 901 */ 902 @NonNull createVirtualKeyboard(@onNull VirtualKeyboardConfig config)903 public VirtualKeyboard createVirtualKeyboard(@NonNull VirtualKeyboardConfig config) { 904 Objects.requireNonNull(config, "config must not be null"); 905 return mVirtualDeviceInternal.createVirtualKeyboard(config); 906 } 907 908 /** 909 * Creates a virtual keyboard. 910 * 911 * @param display the display that the events inputted through this device should target. 912 * @param inputDeviceName the name of this keyboard device. 913 * @param vendorId the PCI vendor id. 914 * @param productId the product id, as defined by the vendor. 915 * @see #createVirtualKeyboard(VirtualKeyboardConfig config) 916 * @deprecated Use {@link #createVirtualKeyboard(VirtualKeyboardConfig config)} instead 917 */ 918 @Deprecated 919 @NonNull createVirtualKeyboard(@onNull VirtualDisplay display, @NonNull String inputDeviceName, int vendorId, int productId)920 public VirtualKeyboard createVirtualKeyboard(@NonNull VirtualDisplay display, 921 @NonNull String inputDeviceName, int vendorId, int productId) { 922 VirtualKeyboardConfig keyboardConfig = 923 new VirtualKeyboardConfig.Builder() 924 .setVendorId(vendorId) 925 .setProductId(productId) 926 .setInputDeviceName(inputDeviceName) 927 .setAssociatedDisplayId(display.getDisplay().getDisplayId()) 928 .build(); 929 return mVirtualDeviceInternal.createVirtualKeyboard(keyboardConfig); 930 } 931 932 /** 933 * Creates a virtual mouse. 934 * 935 * @param config the configurations of the virtual mouse. 936 */ 937 @NonNull createVirtualMouse(@onNull VirtualMouseConfig config)938 public VirtualMouse createVirtualMouse(@NonNull VirtualMouseConfig config) { 939 Objects.requireNonNull(config, "config must not be null"); 940 return mVirtualDeviceInternal.createVirtualMouse(config); 941 } 942 943 /** 944 * Creates a virtual mouse. 945 * 946 * @param display the display that the events inputted through this device should target. 947 * @param inputDeviceName the name of this mouse. 948 * @param vendorId the PCI vendor id. 949 * @param productId the product id, as defined by the vendor. 950 * @see #createVirtualMouse(VirtualMouseConfig config) 951 * @deprecated Use {@link #createVirtualMouse(VirtualMouseConfig config)} instead 952 */ 953 @Deprecated 954 @NonNull createVirtualMouse(@onNull VirtualDisplay display, @NonNull String inputDeviceName, int vendorId, int productId)955 public VirtualMouse createVirtualMouse(@NonNull VirtualDisplay display, 956 @NonNull String inputDeviceName, int vendorId, int productId) { 957 VirtualMouseConfig mouseConfig = 958 new VirtualMouseConfig.Builder() 959 .setVendorId(vendorId) 960 .setProductId(productId) 961 .setInputDeviceName(inputDeviceName) 962 .setAssociatedDisplayId(display.getDisplay().getDisplayId()) 963 .build(); 964 return mVirtualDeviceInternal.createVirtualMouse(mouseConfig); 965 } 966 967 /** 968 * Creates a virtual touchscreen. 969 * 970 * @param config the configurations of the virtual touchscreen. 971 */ 972 @NonNull createVirtualTouchscreen( @onNull VirtualTouchscreenConfig config)973 public VirtualTouchscreen createVirtualTouchscreen( 974 @NonNull VirtualTouchscreenConfig config) { 975 Objects.requireNonNull(config, "config must not be null"); 976 return mVirtualDeviceInternal.createVirtualTouchscreen(config); 977 } 978 979 /** 980 * Creates a virtual touchscreen. 981 * 982 * @param display the display that the events inputted through this device should target. 983 * @param inputDeviceName the name of this touchscreen device. 984 * @param vendorId the PCI vendor id. 985 * @param productId the product id, as defined by the vendor. 986 * @see #createVirtualTouchscreen(VirtualTouchscreenConfig config) 987 * @deprecated Use {@link #createVirtualTouchscreen(VirtualTouchscreenConfig config)} 988 * instead 989 */ 990 @Deprecated 991 @NonNull createVirtualTouchscreen(@onNull VirtualDisplay display, @NonNull String inputDeviceName, int vendorId, int productId)992 public VirtualTouchscreen createVirtualTouchscreen(@NonNull VirtualDisplay display, 993 @NonNull String inputDeviceName, int vendorId, int productId) { 994 final Point size = new Point(); 995 display.getDisplay().getSize(size); 996 VirtualTouchscreenConfig touchscreenConfig = 997 new VirtualTouchscreenConfig.Builder(size.x, size.y) 998 .setVendorId(vendorId) 999 .setProductId(productId) 1000 .setInputDeviceName(inputDeviceName) 1001 .setAssociatedDisplayId(display.getDisplay().getDisplayId()) 1002 .build(); 1003 return mVirtualDeviceInternal.createVirtualTouchscreen(touchscreenConfig); 1004 } 1005 1006 /** 1007 * Creates a virtual touchpad in navigation mode. 1008 * 1009 * <p>A touchpad in navigation mode means that its events are interpreted as navigation 1010 * events (up, down, etc) instead of using them to update a cursor's absolute position. If 1011 * the events are not consumed they are converted to DPAD events and delivered to the target 1012 * again. 1013 * 1014 * @param config the configurations of the virtual navigation touchpad. 1015 * @see android.view.InputDevice#SOURCE_TOUCH_NAVIGATION 1016 */ 1017 @NonNull createVirtualNavigationTouchpad( @onNull VirtualNavigationTouchpadConfig config)1018 public VirtualNavigationTouchpad createVirtualNavigationTouchpad( 1019 @NonNull VirtualNavigationTouchpadConfig config) { 1020 return mVirtualDeviceInternal.createVirtualNavigationTouchpad(config); 1021 } 1022 1023 /** 1024 * Creates a virtual stylus. 1025 * 1026 * @param config the touchscreen configurations for the virtual stylus. 1027 */ 1028 @NonNull createVirtualStylus(@onNull VirtualStylusConfig config)1029 public VirtualStylus createVirtualStylus(@NonNull VirtualStylusConfig config) { 1030 return mVirtualDeviceInternal.createVirtualStylus(config); 1031 } 1032 1033 /** 1034 * Creates a virtual rotary encoder. 1035 * 1036 * @param config the configuration for the virtual rotary encoder. 1037 * @see android.view.InputDevice#SOURCE_ROTARY_ENCODER 1038 */ 1039 @NonNull 1040 @FlaggedApi(Flags.FLAG_VIRTUAL_ROTARY) createVirtualRotaryEncoder( @onNull VirtualRotaryEncoderConfig config)1041 public VirtualRotaryEncoder createVirtualRotaryEncoder( 1042 @NonNull VirtualRotaryEncoderConfig config) { 1043 if (!Flags.virtualRotary()) { 1044 throw new UnsupportedOperationException("Virtual rotary support not enabled"); 1045 } 1046 return mVirtualDeviceInternal.createVirtualRotaryEncoder(config); 1047 } 1048 1049 /** 1050 * Creates a VirtualAudioDevice, capable of recording audio emanating from this device, 1051 * or injecting audio from another device. 1052 * 1053 * <p>Note: One {@link VirtualDevice} can only create one {@link VirtualAudioDevice}, so 1054 * calling this method multiple times will return the same instance. When 1055 * {@link VirtualDevice#close()} is called, the associated {@link VirtualAudioDevice} will 1056 * also be closed automatically. 1057 * 1058 * @param display The target virtual display to capture from and inject into. 1059 * @param executor The {@link Executor} object for the thread on which to execute 1060 * the callback. If <code>null</code>, the {@link Executor} associated with the main 1061 * {@link Looper} will be used. 1062 * @param callback Interface to be notified when playback or recording configuration of 1063 * applications running on virtual display is changed. 1064 * @return A {@link VirtualAudioDevice} instance. 1065 */ 1066 @NonNull createVirtualAudioDevice( @onNull VirtualDisplay display, @Nullable Executor executor, @Nullable AudioConfigurationChangeCallback callback)1067 public VirtualAudioDevice createVirtualAudioDevice( 1068 @NonNull VirtualDisplay display, 1069 @Nullable Executor executor, 1070 @Nullable AudioConfigurationChangeCallback callback) { 1071 Objects.requireNonNull(display, "display must not be null"); 1072 return mVirtualDeviceInternal.createVirtualAudioDevice(display, executor, callback); 1073 } 1074 1075 /** 1076 * Creates a new virtual camera with the given {@link VirtualCameraConfig}. A virtual device 1077 * can create a virtual camera only if it has 1078 * {@link VirtualDeviceParams#DEVICE_POLICY_CUSTOM} as its 1079 * {@link VirtualDeviceParams#POLICY_TYPE_CAMERA}. 1080 * 1081 * @param config camera configuration. 1082 * @return newly created camera. 1083 * @throws UnsupportedOperationException if virtual camera isn't supported on this device. 1084 * @see VirtualDeviceParams#POLICY_TYPE_CAMERA 1085 */ 1086 @NonNull createVirtualCamera(@onNull VirtualCameraConfig config)1087 public VirtualCamera createVirtualCamera(@NonNull VirtualCameraConfig config) { 1088 return mVirtualDeviceInternal.createVirtualCamera(Objects.requireNonNull(config)); 1089 } 1090 1091 /** 1092 * Sets the visibility of the pointer icon for this VirtualDevice's associated displays. 1093 * 1094 * <p>Only applicable to trusted displays.</p> 1095 * 1096 * @param showPointerIcon True if the pointer should be shown; false otherwise. The default 1097 * visibility is true. 1098 * @see DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 1099 */ setShowPointerIcon(boolean showPointerIcon)1100 public void setShowPointerIcon(boolean showPointerIcon) { 1101 mVirtualDeviceInternal.setShowPointerIcon(showPointerIcon); 1102 } 1103 1104 /** 1105 * Specifies the IME behavior on the given display. By default, all displays created by 1106 * virtual devices have {@link WindowManager#DISPLAY_IME_POLICY_LOCAL}. 1107 * 1108 * @param displayId the ID of the display to change the IME policy for. It must be owned by 1109 * this virtual device. 1110 * @param policy the IME policy to use on that display 1111 * @throws SecurityException if the display is not owned by this device or is not 1112 * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED trusted} 1113 */ setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy)1114 public void setDisplayImePolicy(int displayId, @WindowManager.DisplayImePolicy int policy) { 1115 mVirtualDeviceInternal.setDisplayImePolicy(displayId, policy); 1116 } 1117 1118 /** 1119 * Adds an activity listener to listen for events such as top activity change or virtual 1120 * display task stack became empty. 1121 * 1122 * @param executor The executor where the listener is executed on. 1123 * @param listener The listener to add. 1124 * @see #removeActivityListener(ActivityListener) 1125 */ addActivityListener( @allbackExecutor @onNull Executor executor, @NonNull ActivityListener listener)1126 public void addActivityListener( 1127 @CallbackExecutor @NonNull Executor executor, @NonNull ActivityListener listener) { 1128 mVirtualDeviceInternal.addActivityListener(executor, listener); 1129 } 1130 1131 /** 1132 * Removes an activity listener previously added with {@link #addActivityListener}. 1133 * 1134 * @param listener The listener to remove. 1135 * @see #addActivityListener(Executor, ActivityListener) 1136 */ removeActivityListener(@onNull ActivityListener listener)1137 public void removeActivityListener(@NonNull ActivityListener listener) { 1138 mVirtualDeviceInternal.removeActivityListener(listener); 1139 } 1140 1141 /** 1142 * Adds a sound effect listener. 1143 * 1144 * @param executor The executor where the listener is executed on. 1145 * @param soundEffectListener The listener to add. 1146 * @see #removeSoundEffectListener(SoundEffectListener) 1147 */ addSoundEffectListener(@allbackExecutor @onNull Executor executor, @NonNull SoundEffectListener soundEffectListener)1148 public void addSoundEffectListener(@CallbackExecutor @NonNull Executor executor, 1149 @NonNull SoundEffectListener soundEffectListener) { 1150 mVirtualDeviceInternal.addSoundEffectListener(executor, soundEffectListener); 1151 } 1152 1153 /** 1154 * Removes a sound effect listener previously added with {@link #addSoundEffectListener}. 1155 * 1156 * @param soundEffectListener The listener to remove. 1157 * @see #addSoundEffectListener(Executor, SoundEffectListener) 1158 */ removeSoundEffectListener(@onNull SoundEffectListener soundEffectListener)1159 public void removeSoundEffectListener(@NonNull SoundEffectListener soundEffectListener) { 1160 mVirtualDeviceInternal.removeSoundEffectListener(soundEffectListener); 1161 } 1162 1163 /** 1164 * Registers an intent interceptor that will intercept an intent attempting to launch 1165 * when matching the provided IntentFilter and calls the callback with the intercepted 1166 * intent. 1167 * 1168 * @param interceptorFilter The filter to match intents intended for interception. 1169 * @param executor The executor where the interceptor is executed on. 1170 * @param interceptorCallback The callback called when an intent matching interceptorFilter 1171 * is intercepted. 1172 * @see #unregisterIntentInterceptor(IntentInterceptorCallback) 1173 */ registerIntentInterceptor( @onNull IntentFilter interceptorFilter, @CallbackExecutor @NonNull Executor executor, @NonNull IntentInterceptorCallback interceptorCallback)1174 public void registerIntentInterceptor( 1175 @NonNull IntentFilter interceptorFilter, 1176 @CallbackExecutor @NonNull Executor executor, 1177 @NonNull IntentInterceptorCallback interceptorCallback) { 1178 mVirtualDeviceInternal.registerIntentInterceptor( 1179 interceptorFilter, executor, interceptorCallback); 1180 } 1181 1182 /** 1183 * Unregisters the intent interceptor previously registered with 1184 * {@link #registerIntentInterceptor}. 1185 */ unregisterIntentInterceptor( @onNull IntentInterceptorCallback interceptorCallback)1186 public void unregisterIntentInterceptor( 1187 @NonNull IntentInterceptorCallback interceptorCallback) { 1188 mVirtualDeviceInternal.unregisterIntentInterceptor(interceptorCallback); 1189 } 1190 } 1191 1192 /** 1193 * Listener for activity changes and other activity events on a virtual device. 1194 * 1195 * @hide 1196 */ 1197 @SystemApi 1198 public interface ActivityListener { 1199 1200 /** 1201 * Called when the top activity is changed. 1202 * 1203 * <p>Note: When there are no activities running on the virtual display, the 1204 * {@link #onDisplayEmpty(int)} will be called. If the value topActivity is cached, it 1205 * should be cleared when {@link #onDisplayEmpty(int)} is called. 1206 * 1207 * @param displayId The display ID on which the activity change happened. 1208 * @param topActivity The component name of the top activity. 1209 * @deprecated Use {@link #onTopActivityChanged(int, ComponentName, int)} instead 1210 */ onTopActivityChanged(int displayId, @NonNull ComponentName topActivity)1211 void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity); 1212 1213 /** 1214 * Called when the top activity is changed. 1215 * 1216 * <p>Note: When there are no activities running on the virtual display, the 1217 * {@link #onDisplayEmpty(int)} will be called. If the value topActivity is cached, it 1218 * should be cleared when {@link #onDisplayEmpty(int)} is called. 1219 * 1220 * @param displayId The display ID on which the activity change happened. 1221 * @param topActivity The component name of the top activity. 1222 * @param userId The user ID associated with the top activity. 1223 */ onTopActivityChanged(int displayId, @NonNull ComponentName topActivity, @UserIdInt int userId)1224 default void onTopActivityChanged(int displayId, @NonNull ComponentName topActivity, 1225 @UserIdInt int userId) {} 1226 1227 /** 1228 * Called when the display becomes empty (e.g. if the user hits back on the last 1229 * activity of the root task). 1230 * 1231 * @param displayId The display ID that became empty. 1232 */ onDisplayEmpty(int displayId)1233 void onDisplayEmpty(int displayId); 1234 1235 /** 1236 * Called when an activity launch was blocked due to a policy violation. 1237 * 1238 * @param displayId The display ID on which the activity tried to launch. 1239 * @param componentName The component name of the blocked activity. 1240 * @param user The user associated with the blocked activity. 1241 * @param intentSender The original sender of the intent. May be {@code null} if the sender 1242 * expects an activity result to be reported. In that case 1243 * {@link android.app.Activity#RESULT_CANCELED} was already reported back because the 1244 * launch was blocked. This {@link IntentSender} can be used to relaunch the blocked 1245 * activity to a different display. 1246 * 1247 * @see VirtualDeviceParams#POLICY_TYPE_ACTIVITY 1248 * @see VirtualDevice#addActivityPolicyExemption(ActivityPolicyExemption) 1249 */ 1250 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) onActivityLaunchBlocked(int displayId, @NonNull ComponentName componentName, @NonNull UserHandle user, @Nullable IntentSender intentSender)1251 default void onActivityLaunchBlocked(int displayId, @NonNull ComponentName componentName, 1252 @NonNull UserHandle user, @Nullable IntentSender intentSender) {} 1253 1254 /** 1255 * Called when a window with a secure surface is shown on the device. 1256 * 1257 * <p>Note that this is called only when the window is associated with an activity.</p> 1258 * 1259 * @param displayId The display ID on which the window was shown. 1260 * @param componentName The component name of the activity that showed the window. 1261 * @param user The user associated with the activity. 1262 * 1263 * @see Display#FLAG_SECURE 1264 * @see WindowManager.LayoutParams#FLAG_SECURE 1265 */ 1266 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) onSecureWindowShown(int displayId, @NonNull ComponentName componentName, @NonNull UserHandle user)1267 default void onSecureWindowShown(int displayId, @NonNull ComponentName componentName, 1268 @NonNull UserHandle user) {} 1269 1270 /** 1271 * Called when there is no longer any window with a secure surface shown on the device. 1272 * 1273 * <p>This is only called once there are no more secure windows shown on the device. If 1274 * there are multiple secure windows shown on the device, this callback will be called only 1275 * once all of them are hidden.</p> 1276 * 1277 * @param displayId The display ID on which the window was shown before. 1278 * 1279 * @see Display#FLAG_SECURE 1280 * @see WindowManager.LayoutParams#FLAG_SECURE 1281 */ 1282 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) onSecureWindowHidden(int displayId)1283 default void onSecureWindowHidden(int displayId) {} 1284 } 1285 1286 /** 1287 * Interceptor interface to be called when an intent matches the IntentFilter passed into {@link 1288 * VirtualDevice#registerIntentInterceptor}. When the interceptor is called after matching the 1289 * IntentFilter, the intended activity launch will be aborted and alternatively replaced by 1290 * the interceptor's receiver. 1291 * 1292 * @hide 1293 */ 1294 @SystemApi 1295 public interface IntentInterceptorCallback { 1296 1297 /** 1298 * Called when an intent that matches the IntentFilter registered in {@link 1299 * VirtualDevice#registerIntentInterceptor} is intercepted for the virtual device to 1300 * handle. 1301 * 1302 * @param intent The intent that has been intercepted by the interceptor. 1303 */ onIntentIntercepted(@onNull Intent intent)1304 void onIntentIntercepted(@NonNull Intent intent); 1305 } 1306 1307 /** 1308 * Listener for system sound effect playback on virtual device. 1309 * 1310 * @hide 1311 */ 1312 @SystemApi 1313 public interface SoundEffectListener { 1314 1315 /** 1316 * Called when there's a system sound effect to be played on virtual device. 1317 * 1318 * @param effectType - system sound effect type 1319 * @see android.media.AudioManager.SystemSoundEffect 1320 */ onPlaySoundEffect(@udioManager.SystemSoundEffect int effectType)1321 void onPlaySoundEffect(@AudioManager.SystemSoundEffect int effectType); 1322 } 1323 1324 /** 1325 * Listener for changes in the available virtual devices. 1326 * 1327 * @see #registerVirtualDeviceListener 1328 */ 1329 public interface VirtualDeviceListener { 1330 /** 1331 * Called whenever a new virtual device has been added to the system. 1332 * Use {@link VirtualDeviceManager#getVirtualDevice(int)} to get more information about 1333 * the device. 1334 * 1335 * @param deviceId The id of the virtual device that was added. 1336 */ onVirtualDeviceCreated(int deviceId)1337 default void onVirtualDeviceCreated(int deviceId) {} 1338 1339 /** 1340 * Called whenever a virtual device has been removed from the system. 1341 * 1342 * @param deviceId The id of the virtual device that was removed. 1343 */ onVirtualDeviceClosed(int deviceId)1344 default void onVirtualDeviceClosed(int deviceId) {} 1345 } 1346 1347 /** 1348 * A wrapper for {@link VirtualDeviceListener} that executes callbacks on the given executor. 1349 */ 1350 private static class VirtualDeviceListenerDelegate extends IVirtualDeviceListener.Stub { 1351 private final VirtualDeviceListener mListener; 1352 private final Executor mExecutor; 1353 VirtualDeviceListenerDelegate(Executor executor, VirtualDeviceListener listener)1354 private VirtualDeviceListenerDelegate(Executor executor, VirtualDeviceListener listener) { 1355 mExecutor = executor; 1356 mListener = listener; 1357 } 1358 1359 @Override onVirtualDeviceCreated(int deviceId)1360 public void onVirtualDeviceCreated(int deviceId) { 1361 final long token = Binder.clearCallingIdentity(); 1362 try { 1363 mExecutor.execute(() -> mListener.onVirtualDeviceCreated(deviceId)); 1364 } finally { 1365 Binder.restoreCallingIdentity(token); 1366 } 1367 } 1368 1369 @Override onVirtualDeviceClosed(int deviceId)1370 public void onVirtualDeviceClosed(int deviceId) { 1371 final long token = Binder.clearCallingIdentity(); 1372 try { 1373 mExecutor.execute(() -> mListener.onVirtualDeviceClosed(deviceId)); 1374 } finally { 1375 Binder.restoreCallingIdentity(token); 1376 } 1377 } 1378 } 1379 } 1380