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