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.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY; 20 import static android.media.AudioManager.AUDIO_SESSION_ID_GENERATE; 21 22 import static java.util.concurrent.TimeUnit.MICROSECONDS; 23 24 import android.annotation.CallbackExecutor; 25 import android.annotation.FlaggedApi; 26 import android.annotation.IntDef; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.RequiresPermission; 30 import android.annotation.SuppressLint; 31 import android.annotation.SystemApi; 32 import android.companion.virtual.sensor.IVirtualSensorCallback; 33 import android.companion.virtual.sensor.VirtualSensor; 34 import android.companion.virtual.sensor.VirtualSensorCallback; 35 import android.companion.virtual.sensor.VirtualSensorConfig; 36 import android.companion.virtual.sensor.VirtualSensorDirectChannelCallback; 37 import android.companion.virtualdevice.flags.Flags; 38 import android.content.ComponentName; 39 import android.content.Context; 40 import android.hardware.display.VirtualDisplayConfig; 41 import android.os.Parcel; 42 import android.os.Parcelable; 43 import android.os.SharedMemory; 44 import android.os.UserHandle; 45 import android.util.ArraySet; 46 import android.util.SparseArray; 47 import android.util.SparseIntArray; 48 49 import java.io.PrintWriter; 50 import java.lang.annotation.ElementType; 51 import java.lang.annotation.Retention; 52 import java.lang.annotation.RetentionPolicy; 53 import java.lang.annotation.Target; 54 import java.time.Duration; 55 import java.util.ArrayList; 56 import java.util.Collections; 57 import java.util.List; 58 import java.util.Objects; 59 import java.util.Set; 60 import java.util.concurrent.Executor; 61 62 /** 63 * Params that can be configured when creating virtual devices. 64 * 65 * @hide 66 */ 67 @SystemApi 68 public final class VirtualDeviceParams implements Parcelable { 69 70 /** @hide */ 71 @IntDef(prefix = "LOCK_STATE_", 72 value = {LOCK_STATE_DEFAULT, LOCK_STATE_ALWAYS_UNLOCKED}) 73 @Retention(RetentionPolicy.SOURCE) 74 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 75 public @interface LockState {} 76 77 /** 78 * Indicates that the lock state of the virtual device will be the same as the default physical 79 * display. 80 */ 81 public static final int LOCK_STATE_DEFAULT = 0; 82 83 /** 84 * Indicates that the lock state of the virtual device should be always unlocked. 85 */ 86 public static final int LOCK_STATE_ALWAYS_UNLOCKED = 1; 87 88 /** @hide */ 89 @IntDef(prefix = "ACTIVITY_POLICY_", 90 value = {ACTIVITY_POLICY_DEFAULT_ALLOWED, ACTIVITY_POLICY_DEFAULT_BLOCKED}) 91 @Retention(RetentionPolicy.SOURCE) 92 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 93 public @interface ActivityPolicy {} 94 95 /** 96 * Indicates that activities are allowed by default on this virtual device, unless they are 97 * explicitly blocked by {@link Builder#setBlockedActivities}. 98 * 99 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and {@link #DEVICE_POLICY_DEFAULT} 100 */ 101 @Deprecated 102 public static final int ACTIVITY_POLICY_DEFAULT_ALLOWED = 0; 103 104 /** 105 * Indicates that activities are blocked by default on this virtual device, unless they are 106 * allowed by {@link Builder#setAllowedActivities}. 107 * 108 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and {@link #DEVICE_POLICY_CUSTOM} 109 */ 110 @Deprecated 111 public static final int ACTIVITY_POLICY_DEFAULT_BLOCKED = 1; 112 113 /** @hide */ 114 @IntDef(prefix = "NAVIGATION_POLICY_", 115 value = {NAVIGATION_POLICY_DEFAULT_ALLOWED, NAVIGATION_POLICY_DEFAULT_BLOCKED}) 116 @Retention(RetentionPolicy.SOURCE) 117 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 118 public @interface NavigationPolicy {} 119 120 /** 121 * Indicates that tasks are allowed to navigate to other tasks on this virtual device, 122 * unless they are explicitly blocked by {@link Builder#setBlockedCrossTaskNavigations}. 123 * 124 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and {@link #DEVICE_POLICY_DEFAULT} 125 */ 126 @Deprecated 127 public static final int NAVIGATION_POLICY_DEFAULT_ALLOWED = 0; 128 129 /** 130 * Indicates that tasks are blocked from navigating to other tasks by default on this virtual 131 * device, unless allowed by {@link Builder#setAllowedCrossTaskNavigations}. 132 * 133 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and {@link #DEVICE_POLICY_CUSTOM} 134 */ 135 @Deprecated 136 public static final int NAVIGATION_POLICY_DEFAULT_BLOCKED = 1; 137 138 /** @hide */ 139 @IntDef(prefix = "DEVICE_POLICY_", value = {DEVICE_POLICY_DEFAULT, DEVICE_POLICY_CUSTOM}) 140 @Retention(RetentionPolicy.SOURCE) 141 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 142 public @interface DevicePolicy {} 143 144 /** 145 * Indicates that there is no special logic for this virtual device and it should be treated 146 * the same way as the default device, keeping the default behavior unchanged. 147 */ 148 public static final int DEVICE_POLICY_DEFAULT = 0; 149 150 /** 151 * Indicates that there is custom logic, specific to this virtual device, which should be 152 * triggered instead of the default behavior. 153 */ 154 public static final int DEVICE_POLICY_CUSTOM = 1; 155 156 /** 157 * Any relevant component must be able to interpret the correct meaning of a custom policy for 158 * a given policy type. 159 * @hide 160 */ 161 @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_SENSORS, POLICY_TYPE_AUDIO, 162 POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, POLICY_TYPE_CLIPBOARD, POLICY_TYPE_CAMERA, 163 POLICY_TYPE_BLOCKED_ACTIVITY, POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS}) 164 @Retention(RetentionPolicy.SOURCE) 165 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 166 public @interface PolicyType {} 167 168 /** 169 * Policy types that can be dynamically changed during the virtual device's lifetime. 170 * 171 * @see VirtualDeviceManager.VirtualDevice#setDevicePolicy 172 * @hide 173 */ 174 @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY, 175 POLICY_TYPE_CLIPBOARD, POLICY_TYPE_BLOCKED_ACTIVITY}) 176 @Retention(RetentionPolicy.SOURCE) 177 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 178 public @interface DynamicPolicyType {} 179 180 /** 181 * Policy types that can be dynamically changed for a specific display. 182 * 183 * @see VirtualDeviceManager.VirtualDevice#setDevicePolicyForDisplay 184 * @hide 185 */ 186 @IntDef(prefix = "POLICY_TYPE_", value = {POLICY_TYPE_RECENTS, POLICY_TYPE_ACTIVITY}) 187 @Retention(RetentionPolicy.SOURCE) 188 @Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE}) 189 public @interface DynamicDisplayPolicyType {} 190 191 /** 192 * Tells the sensor framework how to handle sensor requests from contexts associated with this 193 * virtual device, namely the sensors returned by 194 * {@link android.hardware.SensorManager#getSensorList}: 195 * 196 * <ul> 197 * <li>{@link #DEVICE_POLICY_DEFAULT}: Return the sensors of the default device. 198 * <li>{@link #DEVICE_POLICY_CUSTOM}: Return the sensors of the virtual device. Note that if 199 * the virtual device did not create any virtual sensors, then an empty list is returned. 200 * </ul> 201 */ 202 public static final int POLICY_TYPE_SENSORS = 0; 203 204 /** 205 * Tells the audio framework whether to configure the players ({@link android.media.AudioTrack}, 206 * {@link android.media.MediaPlayer}, {@link android.media.SoundPool} and recorders 207 * {@link android.media.AudioRecord}) to use specific session ids re-routed to 208 * VirtualAudioDevice. 209 * 210 * <ul> 211 * <li>{@link #DEVICE_POLICY_DEFAULT}: fall back to default session id handling. 212 * <li>{@link #DEVICE_POLICY_CUSTOM}: audio framework will assign device specific session 213 * ids to players and recorders constructed within device context. The session ids are 214 * used to re-route corresponding audio streams to VirtualAudioDevice. 215 * </ul> 216 */ 217 public static final int POLICY_TYPE_AUDIO = 1; 218 219 /** 220 * Tells the activity manager how to handle recents entries for activities run on this device. 221 * 222 * <ul> 223 * <li>{@link #DEVICE_POLICY_DEFAULT}: Activities launched on trusted displays owned by this 224 * device will appear in the host device recents. 225 * <li>{@link #DEVICE_POLICY_CUSTOM}: Activities launched on trusted displays owned by this 226 * device will not appear in recents. 227 * </ul> 228 * 229 * <p>Activities launched on untrusted displays will always show in the host device recents, 230 * regardless of the policy.</p> 231 * 232 * @see android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED 233 */ 234 public static final int POLICY_TYPE_RECENTS = 2; 235 236 /** 237 * Tells the activity manager what the default launch behavior for activities on this device is. 238 * 239 * <ul> 240 * <li>{@link #DEVICE_POLICY_DEFAULT}: Activities are allowed to be launched on displays 241 * owned by this device, unless explicitly blocked by the device. 242 * <li>{@link #DEVICE_POLICY_CUSTOM}: Activities are blocked from launching on displays 243 * owned by this device, unless explicitly allowed by the device. 244 * </ul> 245 * 246 * @see VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption 247 * @see VirtualDeviceManager.VirtualDevice#removeActivityPolicyExemption 248 */ 249 // TODO(b/333443509): Update the documentation of custom policy and link to the new policy 250 // POLICY_TYPE_BLOCKED_ACTIVITY 251 public static final int POLICY_TYPE_ACTIVITY = 3; 252 253 /** 254 * Tells the clipboard manager whether this device's clipboard should be shared or not. 255 * 256 * <ul> 257 * <li>{@link #DEVICE_POLICY_DEFAULT}: By default the device's clipboard is its own and is 258 * not shared with other devices' clipboards, including the clipboard of the default device. 259 * <li>{@link #DEVICE_POLICY_CUSTOM}: The device's clipboard is shared with the default 260 * device's clipboard. Any clipboard operation on the virtual device is as if it was done on 261 * the default device. Requires all displays of the virtual device to be trusted. 262 * </ul> 263 * 264 * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 265 */ 266 public static final int POLICY_TYPE_CLIPBOARD = 4; 267 268 /** 269 * Tells the camera framework how to handle camera requests for the front and back cameras from 270 * contexts associated with this virtual device. 271 * 272 * <ul> 273 * <li>{@link #DEVICE_POLICY_DEFAULT}: Returns the front and back cameras of the default 274 * device. 275 * <li>{@link #DEVICE_POLICY_CUSTOM}: Returns the front and back cameras cameras of the 276 * virtual device. Note that if the virtual device did not create any virtual cameras, 277 * then no front and back cameras will be available. 278 * </ul> 279 * 280 * @see Context#getDeviceId 281 */ 282 public static final int POLICY_TYPE_CAMERA = 5; 283 284 /** 285 * Tells the virtual device framework how to handle activity launches that were blocked due to 286 * the current activity policy. 287 * 288 * <ul> 289 * <li>{@link #DEVICE_POLICY_DEFAULT}: Show UI informing the user of the blocked activity 290 * launch on the virtual display that the activity was originally launched on. 291 * <li>{@link #DEVICE_POLICY_CUSTOM}: Does not inform the user of the blocked activity 292 * launch. The virtual device owner can use this policy together with 293 * {@link VirtualDeviceManager.ActivityListener#onActivityLaunchBlocked} to provide custom 294 * experience on the virtual device. 295 * </ul> 296 */ 297 // TODO(b/333443509): Link to POLICY_TYPE_ACTIVITY 298 @FlaggedApi(Flags.FLAG_ACTIVITY_CONTROL_API) 299 public static final int POLICY_TYPE_BLOCKED_ACTIVITY = 6; 300 301 /** 302 * Tells the virtual device framework how to handle camera access of the default device by apps 303 * running on the virtual device. 304 * 305 * <ul> 306 * <li>{@link #DEVICE_POLICY_DEFAULT}: Default device camera access will be allowed. 307 * <li>{@link #DEVICE_POLICY_CUSTOM}: Default device camera access will be blocked. 308 * </ul> 309 * 310 * @see Context#DEVICE_ID_DEFAULT 311 */ 312 @FlaggedApi(Flags.FLAG_DEFAULT_DEVICE_CAMERA_ACCESS_POLICY) 313 public static final int POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS = 7; 314 315 private final int mLockState; 316 @NonNull private final ArraySet<UserHandle> mUsersWithMatchingAccounts; 317 @NavigationPolicy 318 private final int mDefaultNavigationPolicy; 319 @NonNull private final ArraySet<ComponentName> mCrossTaskNavigationExemptions; 320 @ActivityPolicy 321 private final int mDefaultActivityPolicy; 322 @NonNull private final ArraySet<ComponentName> mActivityPolicyExemptions; 323 @Nullable private final String mName; 324 // Mapping of @PolicyType to @DevicePolicy 325 @NonNull private final SparseIntArray mDevicePolicies; 326 @Nullable private final ComponentName mHomeComponent; 327 @Nullable private final ComponentName mInputMethodComponent; 328 @NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs; 329 @Nullable private final IVirtualSensorCallback mVirtualSensorCallback; 330 private final int mAudioPlaybackSessionId; 331 private final int mAudioRecordingSessionId; 332 private final long mDimDuration; 333 private final long mScreenOffTimeout; 334 VirtualDeviceParams( @ockState int lockState, @NonNull Set<UserHandle> usersWithMatchingAccounts, @NavigationPolicy int defaultNavigationPolicy, @NonNull Set<ComponentName> crossTaskNavigationExemptions, @ActivityPolicy int defaultActivityPolicy, @NonNull Set<ComponentName> activityPolicyExemptions, @Nullable String name, @NonNull SparseIntArray devicePolicies, @Nullable ComponentName homeComponent, @Nullable ComponentName inputMethodComponent, @NonNull List<VirtualSensorConfig> virtualSensorConfigs, @Nullable IVirtualSensorCallback virtualSensorCallback, int audioPlaybackSessionId, int audioRecordingSessionId, long dimDuration, long screenOffTimeout)335 private VirtualDeviceParams( 336 @LockState int lockState, 337 @NonNull Set<UserHandle> usersWithMatchingAccounts, 338 @NavigationPolicy int defaultNavigationPolicy, 339 @NonNull Set<ComponentName> crossTaskNavigationExemptions, 340 @ActivityPolicy int defaultActivityPolicy, 341 @NonNull Set<ComponentName> activityPolicyExemptions, 342 @Nullable String name, 343 @NonNull SparseIntArray devicePolicies, 344 @Nullable ComponentName homeComponent, 345 @Nullable ComponentName inputMethodComponent, 346 @NonNull List<VirtualSensorConfig> virtualSensorConfigs, 347 @Nullable IVirtualSensorCallback virtualSensorCallback, 348 int audioPlaybackSessionId, 349 int audioRecordingSessionId, 350 long dimDuration, 351 long screenOffTimeout) { 352 mLockState = lockState; 353 mUsersWithMatchingAccounts = 354 new ArraySet<>(Objects.requireNonNull(usersWithMatchingAccounts)); 355 mDefaultNavigationPolicy = defaultNavigationPolicy; 356 mCrossTaskNavigationExemptions = 357 new ArraySet<>(Objects.requireNonNull(crossTaskNavigationExemptions)); 358 mDefaultActivityPolicy = defaultActivityPolicy; 359 mActivityPolicyExemptions = 360 new ArraySet<>(Objects.requireNonNull(activityPolicyExemptions)); 361 mName = name; 362 mDevicePolicies = Objects.requireNonNull(devicePolicies); 363 mHomeComponent = homeComponent; 364 mInputMethodComponent = inputMethodComponent; 365 mVirtualSensorConfigs = Objects.requireNonNull(virtualSensorConfigs); 366 mVirtualSensorCallback = virtualSensorCallback; 367 mAudioPlaybackSessionId = audioPlaybackSessionId; 368 mAudioRecordingSessionId = audioRecordingSessionId; 369 mDimDuration = dimDuration; 370 mScreenOffTimeout = screenOffTimeout; 371 } 372 373 @SuppressWarnings("unchecked") VirtualDeviceParams(Parcel parcel)374 private VirtualDeviceParams(Parcel parcel) { 375 mLockState = parcel.readInt(); 376 mUsersWithMatchingAccounts = (ArraySet<UserHandle>) parcel.readArraySet(null); 377 mDefaultNavigationPolicy = parcel.readInt(); 378 mCrossTaskNavigationExemptions = (ArraySet<ComponentName>) parcel.readArraySet(null); 379 mDefaultActivityPolicy = parcel.readInt(); 380 mActivityPolicyExemptions = (ArraySet<ComponentName>) parcel.readArraySet(null); 381 mName = parcel.readString8(); 382 mDevicePolicies = parcel.readSparseIntArray(); 383 mVirtualSensorConfigs = new ArrayList<>(); 384 parcel.readTypedList(mVirtualSensorConfigs, VirtualSensorConfig.CREATOR); 385 mVirtualSensorCallback = 386 IVirtualSensorCallback.Stub.asInterface(parcel.readStrongBinder()); 387 mAudioPlaybackSessionId = parcel.readInt(); 388 mAudioRecordingSessionId = parcel.readInt(); 389 mHomeComponent = parcel.readTypedObject(ComponentName.CREATOR); 390 mInputMethodComponent = parcel.readTypedObject(ComponentName.CREATOR); 391 mDimDuration = parcel.readLong(); 392 mScreenOffTimeout = parcel.readLong(); 393 } 394 395 /** 396 * Returns the lock state of the virtual device. 397 */ 398 @LockState getLockState()399 public int getLockState() { 400 return mLockState; 401 } 402 403 /** 404 * Returns the dim duration for the displays of this device. 405 * 406 * @see Builder#setDimDuration(Duration) 407 */ 408 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) getDimDuration()409 public @NonNull Duration getDimDuration() { 410 return Duration.ofMillis(mDimDuration); 411 } 412 413 /** 414 * Returns the screen off timeout of the displays of this device. 415 * 416 * @see Builder#setDimDuration(Duration) 417 */ 418 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) getScreenOffTimeout()419 public @NonNull Duration getScreenOffTimeout() { 420 return Duration.ofMillis(mScreenOffTimeout); 421 } 422 423 /** 424 * Returns the custom component used as home on all displays owned by this virtual device that 425 * support home activities. 426 * 427 * @see Builder#setHomeComponent 428 * @see VirtualDisplayConfig#isHomeSupported() 429 */ 430 @Nullable getHomeComponent()431 public ComponentName getHomeComponent() { 432 return mHomeComponent; 433 } 434 435 /** 436 * Returns the custom component used as input method on all displays owned by this virtual 437 * device. 438 * 439 * @see Builder#setInputMethodComponent 440 */ 441 @Nullable getInputMethodComponent()442 public ComponentName getInputMethodComponent() { 443 return mInputMethodComponent; 444 } 445 446 /** 447 * Returns the user handles with matching managed accounts on the remote device to which 448 * this virtual device is streaming. 449 * 450 * @see android.app.admin.DevicePolicyManager#NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY 451 */ 452 @NonNull getUsersWithMatchingAccounts()453 public Set<UserHandle> getUsersWithMatchingAccounts() { 454 return Collections.unmodifiableSet(mUsersWithMatchingAccounts); 455 } 456 457 /** 458 * Returns the set of tasks that are allowed to navigate from current task, 459 * or empty set if all tasks are allowed, except the ones explicitly blocked. 460 * If neither allowed or blocked tasks are provided, all task navigations will 461 * be be allowed by default. 462 * 463 * @see Builder#setAllowedCrossTaskNavigations(Set) 464 * 465 * @deprecated See {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 466 */ 467 @Deprecated 468 @NonNull getAllowedCrossTaskNavigations()469 public Set<ComponentName> getAllowedCrossTaskNavigations() { 470 return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_ALLOWED 471 ? Collections.emptySet() 472 : Collections.unmodifiableSet(mCrossTaskNavigationExemptions); 473 } 474 475 /** 476 * Returns the set of tasks that are blocked from navigating from the current task, 477 * or empty set to indicate that all tasks in {@link #getAllowedCrossTaskNavigations} 478 * are allowed. If neither allowed or blocked tasks are provided, all task navigations 479 * will be be allowed by default. 480 * 481 * @see Builder#setBlockedCrossTaskNavigations(Set) 482 * 483 * @deprecated See {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 484 */ 485 @Deprecated 486 @NonNull getBlockedCrossTaskNavigations()487 public Set<ComponentName> getBlockedCrossTaskNavigations() { 488 return mDefaultNavigationPolicy == NAVIGATION_POLICY_DEFAULT_BLOCKED 489 ? Collections.emptySet() 490 : Collections.unmodifiableSet(mCrossTaskNavigationExemptions); 491 } 492 493 /** 494 * Returns {@link #NAVIGATION_POLICY_DEFAULT_ALLOWED} if tasks are allowed to navigate on 495 * this virtual device by default, or {@link #NAVIGATION_POLICY_DEFAULT_BLOCKED} if tasks 496 * must be allowed by {@link Builder#setAllowedCrossTaskNavigations} to navigate here. 497 * 498 * @see Builder#setAllowedCrossTaskNavigations 499 * @see Builder#setBlockedCrossTaskNavigations 500 * 501 * @deprecated Use {@link #getDevicePolicy} with {@link #POLICY_TYPE_ACTIVITY} 502 */ 503 @Deprecated 504 @NavigationPolicy getDefaultNavigationPolicy()505 public int getDefaultNavigationPolicy() { 506 return mDefaultNavigationPolicy; 507 } 508 509 /** 510 * Returns the set of activities allowed to be streamed, or empty set if all activities are 511 * allowed, except the ones explicitly blocked. 512 * 513 * @see Builder#setAllowedActivities(Set) 514 * 515 * @deprecated See {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 516 */ 517 @Deprecated 518 @NonNull getAllowedActivities()519 public Set<ComponentName> getAllowedActivities() { 520 return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_ALLOWED 521 ? Collections.emptySet() 522 : Collections.unmodifiableSet(mActivityPolicyExemptions); 523 } 524 525 /** 526 * Returns the set of activities that are blocked from streaming, or empty set to indicate 527 * that all activities in {@link #getAllowedActivities} are allowed. 528 * 529 * @see Builder#setBlockedActivities(Set) 530 * 531 * @deprecated See {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 532 */ 533 @Deprecated 534 @NonNull getBlockedActivities()535 public Set<ComponentName> getBlockedActivities() { 536 return mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_BLOCKED 537 ? Collections.emptySet() 538 : Collections.unmodifiableSet(mActivityPolicyExemptions); 539 } 540 541 /** 542 * Returns {@link #ACTIVITY_POLICY_DEFAULT_ALLOWED} if activities are allowed to launch on this 543 * virtual device by default, or {@link #ACTIVITY_POLICY_DEFAULT_BLOCKED} if activities must be 544 * allowed by {@link Builder#setAllowedActivities} to launch here. 545 * 546 * @see Builder#setBlockedActivities 547 * @see Builder#setAllowedActivities 548 * 549 * @deprecated Use {@link #getDevicePolicy} with {@link #POLICY_TYPE_ACTIVITY} 550 */ 551 @Deprecated 552 @ActivityPolicy getDefaultActivityPolicy()553 public int getDefaultActivityPolicy() { 554 return mDefaultActivityPolicy; 555 } 556 557 /** 558 * Returns the (optional) name of the virtual device. 559 * 560 * @see Builder#setName 561 */ 562 @Nullable getName()563 public String getName() { 564 return mName; 565 } 566 567 /** 568 * Returns the policy specified for this policy type, or {@link #DEVICE_POLICY_DEFAULT} if no 569 * policy for this type has been explicitly specified. 570 * 571 * @see Builder#setDevicePolicy 572 */ getDevicePolicy(@olicyType int policyType)573 public @DevicePolicy int getDevicePolicy(@PolicyType int policyType) { 574 return mDevicePolicies.get(policyType, DEVICE_POLICY_DEFAULT); 575 } 576 577 /** 578 * Returns all device policies. 579 * @hide 580 */ getDevicePolicies()581 public @NonNull SparseIntArray getDevicePolicies() { 582 return mDevicePolicies; 583 } 584 585 /** 586 * Returns the configurations for all sensors that should be created for this device. 587 * 588 * @see Builder#addVirtualSensorConfig 589 */ getVirtualSensorConfigs()590 public @NonNull List<VirtualSensorConfig> getVirtualSensorConfigs() { 591 return mVirtualSensorConfigs; 592 } 593 594 /** 595 * Returns the callback to get notified about changes in the sensor listeners or sensor direct 596 * channel configuration. 597 * @hide 598 */ 599 @Nullable getVirtualSensorCallback()600 public IVirtualSensorCallback getVirtualSensorCallback() { 601 return mVirtualSensorCallback; 602 } 603 604 /** 605 * Returns device-specific audio session id for playback. 606 * 607 * @see Builder#setAudioPlaybackSessionId(int) 608 */ getAudioPlaybackSessionId()609 public int getAudioPlaybackSessionId() { 610 return mAudioPlaybackSessionId; 611 } 612 613 /** 614 * Returns device-specific audio session id for recording. 615 * 616 * @see Builder#setAudioRecordingSessionId(int) 617 */ getAudioRecordingSessionId()618 public int getAudioRecordingSessionId() { 619 return mAudioRecordingSessionId; 620 } 621 622 @Override describeContents()623 public int describeContents() { 624 return 0; 625 } 626 627 @Override writeToParcel(@onNull Parcel dest, int flags)628 public void writeToParcel(@NonNull Parcel dest, int flags) { 629 dest.writeInt(mLockState); 630 dest.writeArraySet(mUsersWithMatchingAccounts); 631 dest.writeInt(mDefaultNavigationPolicy); 632 dest.writeArraySet(mCrossTaskNavigationExemptions); 633 dest.writeInt(mDefaultActivityPolicy); 634 dest.writeArraySet(mActivityPolicyExemptions); 635 dest.writeString8(mName); 636 dest.writeSparseIntArray(mDevicePolicies); 637 dest.writeTypedList(mVirtualSensorConfigs); 638 dest.writeStrongBinder( 639 mVirtualSensorCallback != null ? mVirtualSensorCallback.asBinder() : null); 640 dest.writeInt(mAudioPlaybackSessionId); 641 dest.writeInt(mAudioRecordingSessionId); 642 dest.writeTypedObject(mHomeComponent, flags); 643 dest.writeTypedObject(mInputMethodComponent, flags); 644 dest.writeLong(mDimDuration); 645 dest.writeLong(mScreenOffTimeout); 646 } 647 648 @Override equals(Object o)649 public boolean equals(Object o) { 650 if (this == o) { 651 return true; 652 } 653 if (!(o instanceof VirtualDeviceParams)) { 654 return false; 655 } 656 VirtualDeviceParams that = (VirtualDeviceParams) o; 657 final int devicePoliciesCount = mDevicePolicies.size(); 658 if (devicePoliciesCount != that.mDevicePolicies.size()) { 659 return false; 660 } 661 for (int i = 0; i < devicePoliciesCount; i++) { 662 if (mDevicePolicies.keyAt(i) != that.mDevicePolicies.keyAt(i)) { 663 return false; 664 } 665 if (mDevicePolicies.valueAt(i) != that.mDevicePolicies.valueAt(i)) { 666 return false; 667 } 668 } 669 return mLockState == that.mLockState 670 && mUsersWithMatchingAccounts.equals(that.mUsersWithMatchingAccounts) 671 && Objects.equals( 672 mCrossTaskNavigationExemptions, that.mCrossTaskNavigationExemptions) 673 && mDefaultNavigationPolicy == that.mDefaultNavigationPolicy 674 && Objects.equals(mActivityPolicyExemptions, that.mActivityPolicyExemptions) 675 && mDefaultActivityPolicy == that.mDefaultActivityPolicy 676 && Objects.equals(mName, that.mName) 677 && Objects.equals(mHomeComponent, that.mHomeComponent) 678 && Objects.equals(mInputMethodComponent, that.mInputMethodComponent) 679 && mAudioPlaybackSessionId == that.mAudioPlaybackSessionId 680 && mAudioRecordingSessionId == that.mAudioRecordingSessionId 681 && mDimDuration == that.mDimDuration 682 && mScreenOffTimeout == that.mScreenOffTimeout; 683 } 684 685 @Override hashCode()686 public int hashCode() { 687 int hashCode = Objects.hash( 688 mLockState, mUsersWithMatchingAccounts, mCrossTaskNavigationExemptions, 689 mDefaultNavigationPolicy, mActivityPolicyExemptions, mDefaultActivityPolicy, mName, 690 mDevicePolicies, mHomeComponent, mInputMethodComponent, mAudioPlaybackSessionId, 691 mAudioRecordingSessionId, mDimDuration, mScreenOffTimeout); 692 for (int i = 0; i < mDevicePolicies.size(); i++) { 693 hashCode = 31 * hashCode + mDevicePolicies.keyAt(i); 694 hashCode = 31 * hashCode + mDevicePolicies.valueAt(i); 695 } 696 return hashCode; 697 } 698 699 @Override 700 @NonNull toString()701 public String toString() { 702 return "VirtualDeviceParams(" 703 + " mLockState=" + mLockState 704 + " mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts 705 + " mDefaultNavigationPolicy=" + mDefaultNavigationPolicy 706 + " mCrossTaskNavigationExemptions=" + mCrossTaskNavigationExemptions 707 + " mDefaultActivityPolicy=" + mDefaultActivityPolicy 708 + " mActivityPolicyExemptions=" + mActivityPolicyExemptions 709 + " mName=" + mName 710 + " mDevicePolicies=" + mDevicePolicies 711 + " mHomeComponent=" + mHomeComponent 712 + " mInputMethodComponent=" + mInputMethodComponent 713 + " mAudioPlaybackSessionId=" + mAudioPlaybackSessionId 714 + " mAudioRecordingSessionId=" + mAudioRecordingSessionId 715 + " mDimDuration=" + mDimDuration 716 + " mScreenOffTimeout=" + mScreenOffTimeout 717 + ")"; 718 } 719 720 /** 721 * Dumps debugging information about the VirtualDeviceParams 722 * @hide 723 */ dump(PrintWriter pw, String prefix)724 public void dump(PrintWriter pw, String prefix) { 725 pw.println(prefix + "mName=" + mName); 726 pw.println(prefix + "mLockState=" + mLockState); 727 pw.println(prefix + "mUsersWithMatchingAccounts=" + mUsersWithMatchingAccounts); 728 pw.println(prefix + "mDefaultNavigationPolicy=" + mDefaultNavigationPolicy); 729 pw.println(prefix + "mCrossTaskNavigationExemptions=" + mCrossTaskNavigationExemptions); 730 pw.println(prefix + "mDefaultActivityPolicy=" + mDefaultActivityPolicy); 731 pw.println(prefix + "mActivityPolicyExemptions=" + mActivityPolicyExemptions); 732 pw.println(prefix + "mDevicePolicies=" + mDevicePolicies); 733 pw.println(prefix + "mVirtualSensorConfigs=" + mVirtualSensorConfigs); 734 pw.println(prefix + "mHomeComponent=" + mHomeComponent); 735 pw.println(prefix + "mInputMethodComponent=" + mInputMethodComponent); 736 pw.println(prefix + "mAudioPlaybackSessionId=" + mAudioPlaybackSessionId); 737 pw.println(prefix + "mAudioRecordingSessionId=" + mAudioRecordingSessionId); 738 pw.println(prefix + "mDimDuration=" + mDimDuration); 739 pw.println(prefix + "mScreenOffTimeout=" + mScreenOffTimeout); 740 } 741 742 @NonNull 743 public static final Parcelable.Creator<VirtualDeviceParams> CREATOR = 744 new Parcelable.Creator<>() { 745 public VirtualDeviceParams createFromParcel(Parcel in) { 746 return new VirtualDeviceParams(in); 747 } 748 749 public VirtualDeviceParams[] newArray(int size) { 750 return new VirtualDeviceParams[size]; 751 } 752 }; 753 754 /** 755 * Builder for {@link VirtualDeviceParams}. 756 */ 757 public static final class Builder { 758 759 private static final Duration INFINITE_TIMEOUT = Duration.ofDays(365 * 1000); 760 761 private @LockState int mLockState = LOCK_STATE_DEFAULT; 762 @NonNull private Set<UserHandle> mUsersWithMatchingAccounts = Collections.emptySet(); 763 @NonNull private Set<ComponentName> mCrossTaskNavigationExemptions = Collections.emptySet(); 764 @NavigationPolicy 765 private int mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED; 766 private boolean mDefaultNavigationPolicyConfigured = false; 767 @NonNull private Set<ComponentName> mActivityPolicyExemptions = Collections.emptySet(); 768 @ActivityPolicy 769 private int mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED; 770 private boolean mDefaultActivityPolicyConfigured = false; 771 @Nullable private String mName; 772 @NonNull private final SparseIntArray mDevicePolicies = new SparseIntArray(); 773 private int mAudioPlaybackSessionId = AUDIO_SESSION_ID_GENERATE; 774 private int mAudioRecordingSessionId = AUDIO_SESSION_ID_GENERATE; 775 776 @NonNull private final List<VirtualSensorConfig> mVirtualSensorConfigs = new ArrayList<>(); 777 @Nullable private Executor mVirtualSensorCallbackExecutor; 778 @Nullable private VirtualSensorCallback mVirtualSensorCallback; 779 @Nullable private Executor mVirtualSensorDirectChannelCallbackExecutor; 780 @Nullable private VirtualSensorDirectChannelCallback mVirtualSensorDirectChannelCallback; 781 @Nullable private ComponentName mHomeComponent; 782 @Nullable private ComponentName mInputMethodComponent; 783 private Duration mDimDuration = Duration.ZERO; 784 private Duration mScreenOffTimeout = Duration.ZERO; 785 786 private static class VirtualSensorCallbackDelegate extends IVirtualSensorCallback.Stub { 787 @NonNull 788 private final Executor mExecutor; 789 @NonNull 790 private final VirtualSensorCallback mCallback; 791 @Nullable 792 private final Executor mDirectChannelExecutor; 793 @Nullable 794 private final VirtualSensorDirectChannelCallback mDirectChannelCallback; 795 VirtualSensorCallbackDelegate(@onNull @allbackExecutor Executor executor, @NonNull VirtualSensorCallback callback, @Nullable @CallbackExecutor Executor directChannelExecutor, @Nullable VirtualSensorDirectChannelCallback directChannelCallback)796 VirtualSensorCallbackDelegate(@NonNull @CallbackExecutor Executor executor, 797 @NonNull VirtualSensorCallback callback, 798 @Nullable @CallbackExecutor Executor directChannelExecutor, 799 @Nullable VirtualSensorDirectChannelCallback directChannelCallback) { 800 mExecutor = executor; 801 mCallback = callback; 802 mDirectChannelExecutor = directChannelExecutor; 803 mDirectChannelCallback = directChannelCallback; 804 } 805 806 @Override onConfigurationChanged(@onNull VirtualSensor sensor, boolean enabled, int samplingPeriodMicros, int batchReportLatencyMicros)807 public void onConfigurationChanged(@NonNull VirtualSensor sensor, boolean enabled, 808 int samplingPeriodMicros, int batchReportLatencyMicros) { 809 final Duration samplingPeriod = 810 Duration.ofNanos(MICROSECONDS.toNanos(samplingPeriodMicros)); 811 final Duration batchReportingLatency = 812 Duration.ofNanos(MICROSECONDS.toNanos(batchReportLatencyMicros)); 813 mExecutor.execute(() -> mCallback.onConfigurationChanged( 814 sensor, enabled, samplingPeriod, batchReportingLatency)); 815 } 816 817 @Override onDirectChannelCreated(int channelHandle, @NonNull SharedMemory sharedMemory)818 public void onDirectChannelCreated(int channelHandle, 819 @NonNull SharedMemory sharedMemory) { 820 if (mDirectChannelCallback != null && mDirectChannelExecutor != null) { 821 mDirectChannelExecutor.execute( 822 () -> mDirectChannelCallback.onDirectChannelCreated(channelHandle, 823 sharedMemory)); 824 } 825 } 826 827 @Override onDirectChannelDestroyed(int channelHandle)828 public void onDirectChannelDestroyed(int channelHandle) { 829 if (mDirectChannelCallback != null && mDirectChannelExecutor != null) { 830 mDirectChannelExecutor.execute( 831 () -> mDirectChannelCallback.onDirectChannelDestroyed(channelHandle)); 832 } 833 } 834 835 @Override onDirectChannelConfigured(int channelHandle, @NonNull VirtualSensor sensor, int rateLevel, int reportToken)836 public void onDirectChannelConfigured(int channelHandle, @NonNull VirtualSensor sensor, 837 int rateLevel, int reportToken) { 838 if (mDirectChannelCallback != null && mDirectChannelExecutor != null) { 839 mDirectChannelExecutor.execute( 840 () -> mDirectChannelCallback.onDirectChannelConfigured( 841 channelHandle, sensor, rateLevel, reportToken)); 842 } 843 } 844 } 845 846 /** 847 * Sets the lock state of the device. The permission {@code ADD_ALWAYS_UNLOCKED_DISPLAY} 848 * is required if this is set to {@link #LOCK_STATE_ALWAYS_UNLOCKED}. 849 * The default is {@link #LOCK_STATE_DEFAULT}. 850 * 851 * @param lockState The lock state, either {@link #LOCK_STATE_DEFAULT} or 852 * {@link #LOCK_STATE_ALWAYS_UNLOCKED}. 853 */ 854 @RequiresPermission(value = ADD_ALWAYS_UNLOCKED_DISPLAY, conditional = true) 855 @NonNull setLockState(@ockState int lockState)856 public Builder setLockState(@LockState int lockState) { 857 mLockState = lockState; 858 return this; 859 } 860 861 /** 862 * Sets the dim duration for all trusted non-mirror displays of the device. 863 * 864 * <p>The system will reduce the display brightness for the specified duration if there 865 * has been no interaction just before the displays turn off.</p> 866 * 867 * <p>If set, the screen off timeout must also be set to a value larger than the dim 868 * duration. If left unset or set to zero, then the display brightness will not be reduced. 869 * </p> 870 * 871 * @throws IllegalArgumentException if the dim duration is negative or if the dim duration 872 * is longer than the screen off timeout. 873 * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 874 * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 875 * @see #setScreenOffTimeout 876 */ 877 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) 878 @NonNull setDimDuration(@onNull Duration dimDuration)879 public Builder setDimDuration(@NonNull Duration dimDuration) { 880 if (Objects.requireNonNull(dimDuration).compareTo(Duration.ZERO) < 0) { 881 throw new IllegalArgumentException("The dim duration cannot be negative"); 882 } 883 mDimDuration = dimDuration; 884 return this; 885 } 886 887 /** 888 * Sets the timeout, after which all trusted non-mirror displays of the device will turn 889 * off, if there has been no interaction with the device. 890 * 891 * <p>If dim duration is set, the screen off timeout must be set to a value larger than the 892 * dim duration. If left unset or set to zero, then the displays will never be turned off 893 * due to inactivity.</p> 894 * 895 * @throws IllegalArgumentException if the screen off timeout is negative or if the dim 896 * duration is longer than the screen off timeout. 897 * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 898 * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR 899 * @see #setDimDuration 900 * @see VirtualDeviceManager.VirtualDevice#goToSleep() 901 */ 902 @FlaggedApi(Flags.FLAG_DEVICE_AWARE_DISPLAY_POWER) 903 @NonNull setScreenOffTimeout(@onNull Duration screenOffTimeout)904 public Builder setScreenOffTimeout(@NonNull Duration screenOffTimeout) { 905 if (Objects.requireNonNull(screenOffTimeout).compareTo(Duration.ZERO) < 0) { 906 throw new IllegalArgumentException("The screen off timeout cannot be negative"); 907 } 908 mScreenOffTimeout = screenOffTimeout; 909 return this; 910 } 911 912 /** 913 * Specifies a component to be used as home on all displays owned by this virtual device 914 * that support home activities. 915 * * 916 * <p>Note: Only relevant for virtual displays that support home activities.</p> 917 * 918 * @param homeComponent The component name to be used as home. If unset, then the system- 919 * default secondary home activity will be used. 920 * 921 * @see VirtualDisplayConfig#isHomeSupported() 922 */ 923 @NonNull setHomeComponent(@ullable ComponentName homeComponent)924 public Builder setHomeComponent(@Nullable ComponentName homeComponent) { 925 mHomeComponent = homeComponent; 926 return this; 927 } 928 929 /** 930 * Specifies a component to be used as input method on all trusted displays owned by this 931 * virtual device. 932 * 933 * @param inputMethodComponent The component name to be used as input method. Must comply to 934 * all general input method requirements described in the guide to 935 * <a href="{@docRoot}guide/topics/text/creating-input-method.html"> 936 * Creating an Input Method</a>. If the given component is not available for any user that 937 * may interact with the virtual device, then there will effectively be no IME on this 938 * device's displays for that user. 939 * 940 * @see android.hardware.display.DisplayManager#VIRTUAL_DISPLAY_FLAG_TRUSTED 941 * @see android.inputmethodservice.InputMethodService 942 * @attr ref android.R.styleable#InputMethod_isVirtualDeviceOnly 943 * @attr ref android.R.styleable#InputMethod_showInInputMethodPicker 944 */ 945 @NonNull setInputMethodComponent(@ullable ComponentName inputMethodComponent)946 public Builder setInputMethodComponent(@Nullable ComponentName inputMethodComponent) { 947 mInputMethodComponent = inputMethodComponent; 948 return this; 949 } 950 951 /** 952 * Sets the user handles with matching managed accounts on the remote device to which 953 * this virtual device is streaming. The caller is responsible for verifying the presence 954 * and legitimacy of a matching managed account on the remote device. 955 * 956 * <p>If the app streaming policy is 957 * {@link android.app.admin.DevicePolicyManager#NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY 958 * NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY}, activities not in 959 * {@code usersWithMatchingAccounts} will be blocked from starting. 960 * 961 * <p> If {@code usersWithMatchingAccounts} is empty (the default), streaming is allowed 962 * only if there is no device policy, or if the nearby streaming policy is 963 * {@link android.app.admin.DevicePolicyManager#NEARBY_STREAMING_ENABLED 964 * NEARBY_STREAMING_ENABLED}. 965 * 966 * @param usersWithMatchingAccounts A set of user handles with matching managed 967 * accounts on the remote device this is streaming to. 968 * 969 * @see android.app.admin.DevicePolicyManager#NEARBY_STREAMING_SAME_MANAGED_ACCOUNT_ONLY 970 */ 971 @NonNull setUsersWithMatchingAccounts( @onNull Set<UserHandle> usersWithMatchingAccounts)972 public Builder setUsersWithMatchingAccounts( 973 @NonNull Set<UserHandle> usersWithMatchingAccounts) { 974 mUsersWithMatchingAccounts = Objects.requireNonNull(usersWithMatchingAccounts); 975 return this; 976 } 977 978 /** 979 * Sets the tasks allowed to navigate from current task in the virtual device. Tasks 980 * not in {@code allowedCrossTaskNavigations} will be blocked from navigating to a new 981 * task. Calling this method will cause {@link #getDefaultNavigationPolicy()} to be 982 * {@link #NAVIGATION_POLICY_DEFAULT_BLOCKED}, meaning tasks not in 983 * {@code allowedCrossTaskNavigations} will be blocked from navigating here. 984 * 985 * <p>This method must not be called if {@link #setBlockedCrossTaskNavigations(Set)} has 986 * been called. 987 * 988 * @throws IllegalArgumentException if {@link #setBlockedCrossTaskNavigations(Set)} has been 989 * called. 990 * 991 * @param allowedCrossTaskNavigations A set of tasks {@link ComponentName} allowed to 992 * navigate to new tasks in the virtual device. 993 * 994 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and 995 * {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 996 */ 997 @Deprecated 998 @NonNull setAllowedCrossTaskNavigations( @onNull Set<ComponentName> allowedCrossTaskNavigations)999 public Builder setAllowedCrossTaskNavigations( 1000 @NonNull Set<ComponentName> allowedCrossTaskNavigations) { 1001 if (mDefaultNavigationPolicyConfigured 1002 && mDefaultNavigationPolicy != NAVIGATION_POLICY_DEFAULT_BLOCKED) { 1003 throw new IllegalArgumentException( 1004 "Allowed cross task navigations and blocked cross task navigations cannot " 1005 + " both be set."); 1006 } 1007 mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_BLOCKED; 1008 mDefaultNavigationPolicyConfigured = true; 1009 mCrossTaskNavigationExemptions = Objects.requireNonNull(allowedCrossTaskNavigations); 1010 return this; 1011 } 1012 1013 /** 1014 * Sets the tasks blocked from navigating from current task in the virtual device. 1015 * Tasks are allowed to navigate unless they are in 1016 * {@code blockedCrossTaskNavigations}. Calling this method will cause 1017 * {@link #NAVIGATION_POLICY_DEFAULT_ALLOWED}, meaning activities are allowed to launch 1018 * unless they are in {@code blockedCrossTaskNavigations}. 1019 * 1020 * <p>This method must not be called if {@link #setAllowedCrossTaskNavigations(Set)} has 1021 * been called. 1022 * 1023 * @throws IllegalArgumentException if {@link #setAllowedCrossTaskNavigations(Set)} has 1024 * been called. 1025 * 1026 * @param blockedCrossTaskNavigations A set of tasks {@link ComponentName} to be 1027 * blocked from navigating to new tasks in the virtual device. 1028 * 1029 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and 1030 * {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 1031 */ 1032 @Deprecated 1033 @NonNull setBlockedCrossTaskNavigations( @onNull Set<ComponentName> blockedCrossTaskNavigations)1034 public Builder setBlockedCrossTaskNavigations( 1035 @NonNull Set<ComponentName> blockedCrossTaskNavigations) { 1036 if (mDefaultNavigationPolicyConfigured 1037 && mDefaultNavigationPolicy != NAVIGATION_POLICY_DEFAULT_ALLOWED) { 1038 throw new IllegalArgumentException( 1039 "Allowed cross task navigation and blocked task navigation cannot " 1040 + " be set."); 1041 } 1042 mDefaultNavigationPolicy = NAVIGATION_POLICY_DEFAULT_ALLOWED; 1043 mDefaultNavigationPolicyConfigured = true; 1044 mCrossTaskNavigationExemptions = Objects.requireNonNull(blockedCrossTaskNavigations); 1045 return this; 1046 } 1047 1048 /** 1049 * Sets the activities allowed to be launched in the virtual device. Calling this method 1050 * will cause {@link #getDefaultActivityPolicy()} to be 1051 * {@link #ACTIVITY_POLICY_DEFAULT_BLOCKED}, meaning activities not in 1052 * {@code allowedActivities} will be blocked from launching here. 1053 * 1054 * <p>This method must not be called if {@link #setBlockedActivities(Set)} has been called. 1055 * 1056 * @throws IllegalArgumentException if {@link #setBlockedActivities(Set)} has been called. 1057 * 1058 * @param allowedActivities A set of activity {@link ComponentName} allowed to be launched 1059 * in the virtual device. 1060 * 1061 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and 1062 * {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 1063 */ 1064 @Deprecated 1065 @NonNull setAllowedActivities(@onNull Set<ComponentName> allowedActivities)1066 public Builder setAllowedActivities(@NonNull Set<ComponentName> allowedActivities) { 1067 if (mDefaultActivityPolicyConfigured 1068 && mDefaultActivityPolicy != ACTIVITY_POLICY_DEFAULT_BLOCKED) { 1069 throw new IllegalArgumentException( 1070 "Allowed activities and Blocked activities cannot both be set."); 1071 } 1072 mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_BLOCKED; 1073 mDefaultActivityPolicyConfigured = true; 1074 mActivityPolicyExemptions = Objects.requireNonNull(allowedActivities); 1075 return this; 1076 } 1077 1078 /** 1079 * Sets the activities blocked from launching in the virtual device. Calling this method 1080 * will cause {@link #getDefaultActivityPolicy()} to be 1081 * {@link #ACTIVITY_POLICY_DEFAULT_ALLOWED}, meaning activities are allowed to launch here 1082 * unless they are in {@code blockedActivities}. 1083 * 1084 * <p>This method must not be called if {@link #setAllowedActivities(Set)} has been called. 1085 * 1086 * @throws IllegalArgumentException if {@link #setAllowedActivities(Set)} has been called. 1087 * 1088 * @param blockedActivities A set of {@link ComponentName} to be blocked launching from 1089 * virtual device. 1090 * 1091 * @deprecated Use {@link #POLICY_TYPE_ACTIVITY} and 1092 * {@link VirtualDeviceManager.VirtualDevice#addActivityPolicyExemption} 1093 */ 1094 @Deprecated 1095 @NonNull setBlockedActivities(@onNull Set<ComponentName> blockedActivities)1096 public Builder setBlockedActivities(@NonNull Set<ComponentName> blockedActivities) { 1097 if (mDefaultActivityPolicyConfigured 1098 && mDefaultActivityPolicy != ACTIVITY_POLICY_DEFAULT_ALLOWED) { 1099 throw new IllegalArgumentException( 1100 "Allowed activities and Blocked activities cannot both be set."); 1101 } 1102 mDefaultActivityPolicy = ACTIVITY_POLICY_DEFAULT_ALLOWED; 1103 mDefaultActivityPolicyConfigured = true; 1104 mActivityPolicyExemptions = Objects.requireNonNull(blockedActivities); 1105 return this; 1106 } 1107 1108 /** 1109 * Sets the optional virtual device name. 1110 * 1111 * <p>This string is not typically intended to be displayed to end users, but rather for 1112 * debugging and other developer-facing purposes. 1113 * 1114 * <p>3rd party applications may be able to see the name (i.e. it's not private to the 1115 * device owner) 1116 */ 1117 @NonNull setName(@onNull String name)1118 public Builder setName(@NonNull String name) { 1119 mName = name; 1120 return this; 1121 } 1122 1123 /** 1124 * Specifies a policy for this virtual device. 1125 * 1126 * <p>Policies define the system behavior that may be specific for this virtual device. A 1127 * policy can be defined for each {@code PolicyType}, but they are all optional. 1128 * 1129 * @param policyType the type of policy, i.e. which behavior to specify a policy for. 1130 * @param devicePolicy the value of the policy, i.e. how to interpret the device behavior. 1131 */ 1132 @NonNull setDevicePolicy(@olicyType int policyType, @DevicePolicy int devicePolicy)1133 public Builder setDevicePolicy(@PolicyType int policyType, @DevicePolicy int devicePolicy) { 1134 mDevicePolicies.put(policyType, devicePolicy); 1135 return this; 1136 } 1137 1138 /** 1139 * Adds a configuration for a sensor that should be created for this virtual device. 1140 * 1141 * <p>Device sensors must remain valid for the entire lifetime of the device, hence they are 1142 * created together with the device itself, and removed when the device is removed. 1143 * 1144 * <p>Requires {@link #DEVICE_POLICY_CUSTOM} to be set for {@link #POLICY_TYPE_SENSORS}. 1145 * 1146 * @see android.companion.virtual.sensor.VirtualSensor 1147 * @see #setDevicePolicy 1148 */ 1149 @NonNull addVirtualSensorConfig(@onNull VirtualSensorConfig virtualSensorConfig)1150 public Builder addVirtualSensorConfig(@NonNull VirtualSensorConfig virtualSensorConfig) { 1151 mVirtualSensorConfigs.add(Objects.requireNonNull(virtualSensorConfig)); 1152 return this; 1153 } 1154 1155 /** 1156 * Sets the callback to get notified about changes in the sensor configuration. 1157 * 1158 * @param executor The executor where the callback is executed on. 1159 * @param callback The callback to get notified when the state of the sensor 1160 * configuration has changed, see {@link VirtualSensorCallback} 1161 */ 1162 @SuppressLint("MissingGetterMatchingBuilder") 1163 @NonNull setVirtualSensorCallback( @onNull @allbackExecutor Executor executor, @NonNull VirtualSensorCallback callback)1164 public Builder setVirtualSensorCallback( 1165 @NonNull @CallbackExecutor Executor executor, 1166 @NonNull VirtualSensorCallback callback) { 1167 mVirtualSensorCallbackExecutor = Objects.requireNonNull(executor); 1168 mVirtualSensorCallback = Objects.requireNonNull(callback); 1169 return this; 1170 } 1171 1172 /** 1173 * Sets the callback to get notified about changes in 1174 * {@link android.hardware.SensorDirectChannel} configuration. 1175 * 1176 * @param executor The executor where the callback is executed on. 1177 * @param callback The callback to get notified when the state of the sensor 1178 * configuration has changed, see {@link VirtualSensorDirectChannelCallback} 1179 */ 1180 @SuppressLint("MissingGetterMatchingBuilder") 1181 @NonNull setVirtualSensorDirectChannelCallback( @onNull @allbackExecutor Executor executor, @NonNull VirtualSensorDirectChannelCallback callback)1182 public Builder setVirtualSensorDirectChannelCallback( 1183 @NonNull @CallbackExecutor Executor executor, 1184 @NonNull VirtualSensorDirectChannelCallback callback) { 1185 mVirtualSensorDirectChannelCallbackExecutor = Objects.requireNonNull(executor); 1186 mVirtualSensorDirectChannelCallback = Objects.requireNonNull(callback); 1187 return this; 1188 } 1189 1190 /** 1191 * Sets audio playback session id specific for this virtual device. 1192 * 1193 * <p>Audio players constructed within context associated with this virtual device 1194 * will be automatically assigned provided session id. 1195 * 1196 * <p>Requires {@link #DEVICE_POLICY_CUSTOM} to be set for {@link #POLICY_TYPE_AUDIO}, 1197 * otherwise {@link #build()} method will throw {@link IllegalArgumentException} if 1198 * the playback session id is set to value other than 1199 * {@link android.media.AudioManager#AUDIO_SESSION_ID_GENERATE}. 1200 * 1201 * @param playbackSessionId requested device-specific audio session id for playback 1202 * @see android.media.AudioManager#generateAudioSessionId() 1203 * @see android.media.AudioTrack.Builder#setContext(Context) 1204 */ 1205 @NonNull setAudioPlaybackSessionId(int playbackSessionId)1206 public Builder setAudioPlaybackSessionId(int playbackSessionId) { 1207 if (playbackSessionId < 0) { 1208 throw new IllegalArgumentException("Invalid playback audio session id"); 1209 } 1210 mAudioPlaybackSessionId = playbackSessionId; 1211 return this; 1212 } 1213 1214 /** 1215 * Sets audio recording session id specific for this virtual device. 1216 * 1217 * <p>{@link android.media.AudioRecord} constructed within context associated with this 1218 * virtual device will be automatically assigned provided session id. 1219 * 1220 * <p>Requires {@link #DEVICE_POLICY_CUSTOM} to be set for {@link #POLICY_TYPE_AUDIO}, 1221 * otherwise {@link #build()} method will throw {@link IllegalArgumentException} if 1222 * the recording session id is set to value other than 1223 * {@link android.media.AudioManager#AUDIO_SESSION_ID_GENERATE}. 1224 * 1225 * @param recordingSessionId requested device-specific audio session id for playback 1226 * @see android.media.AudioManager#generateAudioSessionId() 1227 * @see android.media.AudioRecord.Builder#setContext(Context) 1228 */ 1229 @NonNull setAudioRecordingSessionId(int recordingSessionId)1230 public Builder setAudioRecordingSessionId(int recordingSessionId) { 1231 if (recordingSessionId < 0) { 1232 throw new IllegalArgumentException("Invalid recording audio session id"); 1233 } 1234 mAudioRecordingSessionId = recordingSessionId; 1235 return this; 1236 } 1237 1238 /** 1239 * Builds the {@link VirtualDeviceParams} instance. 1240 * 1241 * @throws IllegalArgumentException if there's mismatch between policy definition and 1242 * the passed parameters or if there are sensor configs with the same type and name. 1243 * 1244 */ 1245 @NonNull build()1246 public VirtualDeviceParams build() { 1247 VirtualSensorCallbackDelegate virtualSensorCallbackDelegate = null; 1248 if (!mVirtualSensorConfigs.isEmpty()) { 1249 if (mDevicePolicies.get(POLICY_TYPE_SENSORS, DEVICE_POLICY_DEFAULT) 1250 != DEVICE_POLICY_CUSTOM) { 1251 throw new IllegalArgumentException( 1252 "DEVICE_POLICY_CUSTOM for POLICY_TYPE_SENSORS is required for creating " 1253 + "virtual sensors."); 1254 } 1255 if (mVirtualSensorCallback == null) { 1256 throw new IllegalArgumentException( 1257 "VirtualSensorCallback is required for creating virtual sensors."); 1258 } 1259 1260 for (int i = 0; i < mVirtualSensorConfigs.size(); ++i) { 1261 if (mVirtualSensorConfigs.get(i).getDirectChannelTypesSupported() > 0) { 1262 if (mVirtualSensorDirectChannelCallback == null) { 1263 throw new IllegalArgumentException( 1264 "VirtualSensorDirectChannelCallback is required for creating " 1265 + "virtual sensors that support direct channel."); 1266 } 1267 break; 1268 } 1269 } 1270 virtualSensorCallbackDelegate = new VirtualSensorCallbackDelegate( 1271 mVirtualSensorCallbackExecutor, 1272 mVirtualSensorCallback, 1273 mVirtualSensorDirectChannelCallbackExecutor, 1274 mVirtualSensorDirectChannelCallback); 1275 } 1276 1277 switch (mDevicePolicies.get(POLICY_TYPE_ACTIVITY, -1)) { 1278 case DEVICE_POLICY_DEFAULT: 1279 if (mDefaultActivityPolicyConfigured 1280 && mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_BLOCKED) { 1281 throw new IllegalArgumentException( 1282 "DEVICE_POLICY_DEFAULT is explicitly configured for " 1283 + "POLICY_TYPE_ACTIVITY, which is exclusive with " 1284 + "setAllowedActivities."); 1285 } 1286 break; 1287 case DEVICE_POLICY_CUSTOM: 1288 if (mDefaultActivityPolicyConfigured 1289 && mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_ALLOWED) { 1290 throw new IllegalArgumentException( 1291 "DEVICE_POLICY_CUSTOM is explicitly configured for " 1292 + "POLICY_TYPE_ACTIVITY, which is exclusive with " 1293 + "setBlockedActivities."); 1294 } 1295 break; 1296 default: 1297 if (mDefaultActivityPolicyConfigured 1298 && mDefaultActivityPolicy == ACTIVITY_POLICY_DEFAULT_BLOCKED) { 1299 mDevicePolicies.put(POLICY_TYPE_ACTIVITY, DEVICE_POLICY_CUSTOM); 1300 } 1301 break; 1302 } 1303 1304 if (mDimDuration.compareTo(mScreenOffTimeout) > 0) { 1305 throw new IllegalArgumentException( 1306 "The dim duration cannot be greater than the screen off timeout."); 1307 } 1308 if (mScreenOffTimeout.compareTo(Duration.ZERO) == 0) { 1309 mScreenOffTimeout = INFINITE_TIMEOUT; 1310 } 1311 1312 if (!Flags.defaultDeviceCameraAccessPolicy()) { 1313 mDevicePolicies.delete(POLICY_TYPE_DEFAULT_DEVICE_CAMERA_ACCESS); 1314 } 1315 1316 if (!Flags.activityControlApi()) { 1317 mDevicePolicies.delete(POLICY_TYPE_BLOCKED_ACTIVITY); 1318 } 1319 1320 if ((mAudioPlaybackSessionId != AUDIO_SESSION_ID_GENERATE 1321 || mAudioRecordingSessionId != AUDIO_SESSION_ID_GENERATE) 1322 && mDevicePolicies.get(POLICY_TYPE_AUDIO, DEVICE_POLICY_DEFAULT) 1323 != DEVICE_POLICY_CUSTOM) { 1324 throw new IllegalArgumentException("DEVICE_POLICY_CUSTOM for POLICY_TYPE_AUDIO is " 1325 + "required for configuration of device-specific audio session ids."); 1326 } 1327 1328 SparseArray<Set<String>> sensorNameByType = new SparseArray<>(); 1329 for (int i = 0; i < mVirtualSensorConfigs.size(); ++i) { 1330 VirtualSensorConfig config = mVirtualSensorConfigs.get(i); 1331 Set<String> sensorNames = sensorNameByType.get(config.getType(), new ArraySet<>()); 1332 if (!sensorNames.add(config.getName())) { 1333 throw new IllegalArgumentException( 1334 "Sensor names must be unique for a particular sensor type."); 1335 } 1336 sensorNameByType.put(config.getType(), sensorNames); 1337 } 1338 1339 return new VirtualDeviceParams( 1340 mLockState, 1341 mUsersWithMatchingAccounts, 1342 mDefaultNavigationPolicy, 1343 mCrossTaskNavigationExemptions, 1344 mDefaultActivityPolicy, 1345 mActivityPolicyExemptions, 1346 mName, 1347 mDevicePolicies, 1348 mHomeComponent, 1349 mInputMethodComponent, 1350 mVirtualSensorConfigs, 1351 virtualSensorCallbackDelegate, 1352 mAudioPlaybackSessionId, 1353 mAudioRecordingSessionId, 1354 mDimDuration.toMillis(), 1355 mScreenOffTimeout.toMillis()); 1356 } 1357 } 1358 } 1359