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