Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -9682,6 +9682,7 @@ package android.companion.virtual { method public int describeContents(); method public int getDeviceId(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @NonNull public int[] getDisplayIds(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @Nullable public CharSequence getDisplayName(); method @Nullable public String getName(); method @Nullable public String getPersistentDeviceId(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") public boolean hasCustomSensorSupport(); core/java/android/companion/virtual/VirtualDevice.java +26 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ public final class VirtualDevice implements Parcelable { private final int mId; private final @Nullable String mPersistentId; private final @Nullable String mName; private final @Nullable CharSequence mDisplayName; /** * Creates a new instance of {@link VirtualDevice}. Loading @@ -53,6 +54,18 @@ public final class VirtualDevice implements Parcelable { */ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id, @Nullable String persistentId, @Nullable String name) { this(virtualDevice, id, persistentId, name, null); } /** * Creates a new instance of {@link VirtualDevice}. Only to be used by the * VirtualDeviceManagerService. * * @hide */ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id, @Nullable String persistentId, @Nullable String name, @Nullable CharSequence displayName) { if (id <= Context.DEVICE_ID_DEFAULT) { throw new IllegalArgumentException("VirtualDevice ID must be greater than " + Context.DEVICE_ID_DEFAULT); Loading @@ -61,6 +74,7 @@ public final class VirtualDevice implements Parcelable { mId = id; mPersistentId = persistentId; mName = name; mDisplayName = displayName; } private VirtualDevice(@NonNull Parcel parcel) { Loading @@ -68,6 +82,7 @@ public final class VirtualDevice implements Parcelable { mId = parcel.readInt(); mPersistentId = parcel.readString8(); mName = parcel.readString8(); mDisplayName = parcel.readCharSequence(); } /** Loading Loading @@ -111,6 +126,15 @@ public final class VirtualDevice implements Parcelable { return mName; } /** * Returns the human-readable name of the virtual device, if defined, which is suitable to be * shown in UI. */ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public @Nullable CharSequence getDisplayName() { return mDisplayName; } /** * Returns the IDs of all virtual displays that belong to this device, if any. * Loading Loading @@ -156,6 +180,7 @@ public final class VirtualDevice implements Parcelable { dest.writeInt(mId); dest.writeString8(mPersistentId); dest.writeString8(mName); dest.writeCharSequence(mDisplayName); } @Override Loading @@ -165,6 +190,7 @@ public final class VirtualDevice implements Parcelable { + " mId=" + mId + " mPersistentId=" + mPersistentId + " mName=" + mName + " mDisplayName=" + mDisplayName + ")"; } Loading core/java/android/companion/virtual/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -34,3 +34,10 @@ flag { description: "Enable Virtual Camera" bug: "270352264" } flag { name: "stream_permissions" namespace: "virtual_devices" description: "Enable streaming permission dialogs to Virtual Devices" bug: "291737919" } services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +11 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController private final boolean mCrossTaskNavigationAllowedByDefault; @NonNull private final ArraySet<ComponentName> mCrossTaskNavigationExemptions; @Nullable private final ComponentName mPermissionDialogComponent; private final Object mGenericWindowPolicyControllerLock = new Object(); @Nullable private final ActivityBlockedCallback mActivityBlockedCallback; private int mDisplayId = Display.INVALID_DISPLAY; Loading Loading @@ -171,6 +173,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @NonNull Set<ComponentName> activityPolicyExemptions, boolean crossTaskNavigationAllowedByDefault, @NonNull Set<ComponentName> crossTaskNavigationExemptions, @Nullable ComponentName permissionDialogComponent, @Nullable ActivityListener activityListener, @Nullable PipBlockedCallback pipBlockedCallback, @Nullable ActivityBlockedCallback activityBlockedCallback, Loading @@ -185,6 +188,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mActivityPolicyExemptions = activityPolicyExemptions; mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault; mCrossTaskNavigationExemptions = new ArraySet<>(crossTaskNavigationExemptions); mPermissionDialogComponent = permissionDialogComponent; mActivityBlockedCallback = activityBlockedCallback; setInterestedWindowFlags(windowFlags, systemWindowFlags); mActivityListener = activityListener; Loading Loading @@ -309,6 +313,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController return false; } // mPermissionDialogComponent being null means we don't want to block permission Dialogs // based on FLAG_STREAM_PERMISSIONS if (mPermissionDialogComponent != null && mPermissionDialogComponent.equals(activityComponent)) { return false; } return true; } Loading services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +23 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAUL import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS; import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; Loading Loading @@ -204,6 +205,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @GuardedBy("mVirtualDeviceLock") @NonNull private final Set<ComponentName> mActivityPolicyExemptions; private final ComponentName mPermissionDialogComponent; private ActivityListener createListenerAdapter() { return new ActivityListener() { Loading Loading @@ -317,6 +319,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getVirtualSensorCallback(), mParams.getVirtualSensorConfigs()); mCameraAccessController = cameraAccessController; mCameraAccessController.startObservingIfNeeded(); if (!Flags.streamPermissions()) { mPermissionDialogComponent = getPermissionDialogComponent(); } else { mPermissionDialogComponent = null; } try { token.linkToDeath(this, 0); } catch (RemoteException e) { Loading @@ -324,8 +331,14 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } mVirtualDeviceLog.logCreated(deviceId, mOwnerUid); if (Flags.vdmPublicApis()) { mPublicVirtualDeviceObject = new VirtualDevice( this, getDeviceId(), getPersistentDeviceId(), mParams.getName(), getDisplayName()); } else { mPublicVirtualDeviceObject = new VirtualDevice( this, getDeviceId(), getPersistentDeviceId(), mParams.getName()); } if (Flags.dynamicPolicy()) { mActivityPolicyExemptions = new ArraySet<>( Loading Loading @@ -951,6 +964,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub /*crossTaskNavigationExemptions=*/crossTaskNavigationAllowedByDefault ? mParams.getBlockedCrossTaskNavigations() : mParams.getAllowedCrossTaskNavigations(), mPermissionDialogComponent, createListenerAdapter(), this::onEnteringPipBlocked, this::onActivityBlocked, Loading @@ -963,6 +977,13 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return gwpc; } private ComponentName getPermissionDialogComponent() { Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS); PackageManager packageManager = mContext.getPackageManager(); intent.setPackage(packageManager.getPermissionControllerPackageName()); return intent.resolveActivity(packageManager); } int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig, @NonNull IVirtualDisplayCallback callback, String packageName) { GenericWindowPolicyController gwpc; Loading Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -9682,6 +9682,7 @@ package android.companion.virtual { method public int describeContents(); method public int getDeviceId(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @NonNull public int[] getDisplayIds(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") @Nullable public CharSequence getDisplayName(); method @Nullable public String getName(); method @Nullable public String getPersistentDeviceId(); method @FlaggedApi("android.companion.virtual.flags.vdm_public_apis") public boolean hasCustomSensorSupport();
core/java/android/companion/virtual/VirtualDevice.java +26 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ public final class VirtualDevice implements Parcelable { private final int mId; private final @Nullable String mPersistentId; private final @Nullable String mName; private final @Nullable CharSequence mDisplayName; /** * Creates a new instance of {@link VirtualDevice}. Loading @@ -53,6 +54,18 @@ public final class VirtualDevice implements Parcelable { */ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id, @Nullable String persistentId, @Nullable String name) { this(virtualDevice, id, persistentId, name, null); } /** * Creates a new instance of {@link VirtualDevice}. Only to be used by the * VirtualDeviceManagerService. * * @hide */ public VirtualDevice(@NonNull IVirtualDevice virtualDevice, int id, @Nullable String persistentId, @Nullable String name, @Nullable CharSequence displayName) { if (id <= Context.DEVICE_ID_DEFAULT) { throw new IllegalArgumentException("VirtualDevice ID must be greater than " + Context.DEVICE_ID_DEFAULT); Loading @@ -61,6 +74,7 @@ public final class VirtualDevice implements Parcelable { mId = id; mPersistentId = persistentId; mName = name; mDisplayName = displayName; } private VirtualDevice(@NonNull Parcel parcel) { Loading @@ -68,6 +82,7 @@ public final class VirtualDevice implements Parcelable { mId = parcel.readInt(); mPersistentId = parcel.readString8(); mName = parcel.readString8(); mDisplayName = parcel.readCharSequence(); } /** Loading Loading @@ -111,6 +126,15 @@ public final class VirtualDevice implements Parcelable { return mName; } /** * Returns the human-readable name of the virtual device, if defined, which is suitable to be * shown in UI. */ @FlaggedApi(Flags.FLAG_VDM_PUBLIC_APIS) public @Nullable CharSequence getDisplayName() { return mDisplayName; } /** * Returns the IDs of all virtual displays that belong to this device, if any. * Loading Loading @@ -156,6 +180,7 @@ public final class VirtualDevice implements Parcelable { dest.writeInt(mId); dest.writeString8(mPersistentId); dest.writeString8(mName); dest.writeCharSequence(mDisplayName); } @Override Loading @@ -165,6 +190,7 @@ public final class VirtualDevice implements Parcelable { + " mId=" + mId + " mPersistentId=" + mPersistentId + " mName=" + mName + " mDisplayName=" + mDisplayName + ")"; } Loading
core/java/android/companion/virtual/flags.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -34,3 +34,10 @@ flag { description: "Enable Virtual Camera" bug: "270352264" } flag { name: "stream_permissions" namespace: "virtual_devices" description: "Enable streaming permission dialogs to Virtual Devices" bug: "291737919" }
services/companion/java/com/android/server/companion/virtual/GenericWindowPolicyController.java +11 −0 Original line number Diff line number Diff line Loading @@ -113,6 +113,8 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController private final boolean mCrossTaskNavigationAllowedByDefault; @NonNull private final ArraySet<ComponentName> mCrossTaskNavigationExemptions; @Nullable private final ComponentName mPermissionDialogComponent; private final Object mGenericWindowPolicyControllerLock = new Object(); @Nullable private final ActivityBlockedCallback mActivityBlockedCallback; private int mDisplayId = Display.INVALID_DISPLAY; Loading Loading @@ -171,6 +173,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController @NonNull Set<ComponentName> activityPolicyExemptions, boolean crossTaskNavigationAllowedByDefault, @NonNull Set<ComponentName> crossTaskNavigationExemptions, @Nullable ComponentName permissionDialogComponent, @Nullable ActivityListener activityListener, @Nullable PipBlockedCallback pipBlockedCallback, @Nullable ActivityBlockedCallback activityBlockedCallback, Loading @@ -185,6 +188,7 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController mActivityPolicyExemptions = activityPolicyExemptions; mCrossTaskNavigationAllowedByDefault = crossTaskNavigationAllowedByDefault; mCrossTaskNavigationExemptions = new ArraySet<>(crossTaskNavigationExemptions); mPermissionDialogComponent = permissionDialogComponent; mActivityBlockedCallback = activityBlockedCallback; setInterestedWindowFlags(windowFlags, systemWindowFlags); mActivityListener = activityListener; Loading Loading @@ -309,6 +313,13 @@ public class GenericWindowPolicyController extends DisplayWindowPolicyController return false; } // mPermissionDialogComponent being null means we don't want to block permission Dialogs // based on FLAG_STREAM_PERMISSIONS if (mPermissionDialogComponent != null && mPermissionDialogComponent.equals(activityComponent)) { return false; } return true; } Loading
services/companion/java/com/android/server/companion/virtual/VirtualDeviceImpl.java +23 −2 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import static android.companion.virtual.VirtualDeviceParams.DEVICE_POLICY_DEFAUL import static android.companion.virtual.VirtualDeviceParams.NAVIGATION_POLICY_DEFAULT_ALLOWED; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_ACTIVITY; import static android.companion.virtual.VirtualDeviceParams.POLICY_TYPE_RECENTS; import static android.content.pm.PackageManager.ACTION_REQUEST_PERMISSIONS; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS; Loading Loading @@ -204,6 +205,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub @GuardedBy("mVirtualDeviceLock") @NonNull private final Set<ComponentName> mActivityPolicyExemptions; private final ComponentName mPermissionDialogComponent; private ActivityListener createListenerAdapter() { return new ActivityListener() { Loading Loading @@ -317,6 +319,11 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub mParams.getVirtualSensorCallback(), mParams.getVirtualSensorConfigs()); mCameraAccessController = cameraAccessController; mCameraAccessController.startObservingIfNeeded(); if (!Flags.streamPermissions()) { mPermissionDialogComponent = getPermissionDialogComponent(); } else { mPermissionDialogComponent = null; } try { token.linkToDeath(this, 0); } catch (RemoteException e) { Loading @@ -324,8 +331,14 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub } mVirtualDeviceLog.logCreated(deviceId, mOwnerUid); if (Flags.vdmPublicApis()) { mPublicVirtualDeviceObject = new VirtualDevice( this, getDeviceId(), getPersistentDeviceId(), mParams.getName(), getDisplayName()); } else { mPublicVirtualDeviceObject = new VirtualDevice( this, getDeviceId(), getPersistentDeviceId(), mParams.getName()); } if (Flags.dynamicPolicy()) { mActivityPolicyExemptions = new ArraySet<>( Loading Loading @@ -951,6 +964,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub /*crossTaskNavigationExemptions=*/crossTaskNavigationAllowedByDefault ? mParams.getBlockedCrossTaskNavigations() : mParams.getAllowedCrossTaskNavigations(), mPermissionDialogComponent, createListenerAdapter(), this::onEnteringPipBlocked, this::onActivityBlocked, Loading @@ -963,6 +977,13 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub return gwpc; } private ComponentName getPermissionDialogComponent() { Intent intent = new Intent(ACTION_REQUEST_PERMISSIONS); PackageManager packageManager = mContext.getPackageManager(); intent.setPackage(packageManager.getPermissionControllerPackageName()); return intent.resolveActivity(packageManager); } int createVirtualDisplay(@NonNull VirtualDisplayConfig virtualDisplayConfig, @NonNull IVirtualDisplayCallback callback, String packageName) { GenericWindowPolicyController gwpc; Loading