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