Add params object to createVirtualDevice
The VirtualDeviceParams are passed into createVirtualDevice to provide additional configuration options to the method. Bug: 194949534 Test: To be added in ag/15781910 Change-Id: Ief9c013a2f1c70a63e3dc3eb8fbc0af60ea65c44
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package android.companion.virtual;
|
||||
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
|
||||
/**
|
||||
* Interface for communication between VirtualDeviceManager and VirtualDeviceManagerService.
|
||||
@@ -33,6 +34,10 @@ interface IVirtualDeviceManager {
|
||||
* that this belongs to the calling UID.
|
||||
* @param associationId The association ID as returned by {@link AssociationInfo#getId()} from
|
||||
* CDM. Virtual devices must have a corresponding association with CDM in order to be created.
|
||||
* @param params The parameters for creating this virtual device. See {@link
|
||||
* VirtualDeviceManager.VirtualDeviceParams}.
|
||||
*/
|
||||
IVirtualDevice createVirtualDevice(in IBinder token, String packageName, int associationId);
|
||||
IVirtualDevice createVirtualDevice(
|
||||
in IBinder token, String packageName, int associationId,
|
||||
in VirtualDeviceParams params);
|
||||
}
|
||||
|
||||
@@ -100,11 +100,11 @@ public final class VirtualDeviceManager {
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
|
||||
@Nullable
|
||||
public VirtualDevice createVirtualDevice(int associationId) {
|
||||
public VirtualDevice createVirtualDevice(int associationId, VirtualDeviceParams params) {
|
||||
// TODO(b/194949534): Unhide this API
|
||||
try {
|
||||
IVirtualDevice virtualDevice = mService.createVirtualDevice(
|
||||
new Binder(), mContext.getPackageName(), associationId);
|
||||
new Binder(), mContext.getPackageName(), associationId, params);
|
||||
return new VirtualDevice(mContext, virtualDevice);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
@@ -273,6 +273,12 @@ public final class VirtualDeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the display flags that should be added to a particular virtual display.
|
||||
* Additional device-level flags from {@link
|
||||
* com.android.server.companion.virtual.VirtualDeviceImpl#getBaseVirtualDisplayFlags()} will
|
||||
* be added by DisplayManagerService.
|
||||
*/
|
||||
private int getVirtualDisplayFlags(@DisplayFlags int flags) {
|
||||
int virtualDisplayFlags = DEFAULT_VIRTUAL_DISPLAY_FLAGS;
|
||||
if ((flags & DISPLAY_FLAG_TRUSTED) != 0) {
|
||||
|
||||
19
core/java/android/companion/virtual/VirtualDeviceParams.aidl
Normal file
19
core/java/android/companion/virtual/VirtualDeviceParams.aidl
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.companion.virtual;
|
||||
|
||||
parcelable VirtualDeviceParams;
|
||||
152
core/java/android/companion/virtual/VirtualDeviceParams.java
Normal file
152
core/java/android/companion/virtual/VirtualDeviceParams.java
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.companion.virtual;
|
||||
|
||||
import static android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Params that can be configured when creating virtual devices.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
// TODO(b/194949534): Unhide this API
|
||||
public final class VirtualDeviceParams implements Parcelable {
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = "LOCK_STATE_",
|
||||
value = {LOCK_STATE_ALWAYS_LOCKED, LOCK_STATE_ALWAYS_UNLOCKED})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ElementType.TYPE_PARAMETER, ElementType.TYPE_USE})
|
||||
public @interface LockState {}
|
||||
|
||||
/**
|
||||
* Indicates that the lock state of the virtual device should be always locked.
|
||||
*
|
||||
* @hide // TODO(b/194949534): Unhide this API
|
||||
*/
|
||||
public static final int LOCK_STATE_ALWAYS_LOCKED = 0;
|
||||
|
||||
/**
|
||||
* Indicates that the lock state of the virtual device should be always unlocked.
|
||||
*
|
||||
* @hide // TODO(b/194949534): Unhide this API
|
||||
*/
|
||||
public static final int LOCK_STATE_ALWAYS_UNLOCKED = 1;
|
||||
|
||||
private final int mLockState;
|
||||
|
||||
private VirtualDeviceParams(@LockState int lockState) {
|
||||
mLockState = lockState;
|
||||
}
|
||||
|
||||
private VirtualDeviceParams(Parcel parcel) {
|
||||
mLockState = parcel.readInt();
|
||||
}
|
||||
|
||||
@LockState
|
||||
public int getLockState() {
|
||||
return mLockState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(mLockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof VirtualDeviceParams)) {
|
||||
return false;
|
||||
}
|
||||
VirtualDeviceParams that = (VirtualDeviceParams) o;
|
||||
return mLockState == that.mLockState;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mLockState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VirtualDeviceParams("
|
||||
+ " mLockState=" + mLockState
|
||||
+ ")";
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<VirtualDeviceParams> CREATOR =
|
||||
new Parcelable.Creator<VirtualDeviceParams>() {
|
||||
public VirtualDeviceParams createFromParcel(Parcel in) {
|
||||
return new VirtualDeviceParams(in);
|
||||
}
|
||||
|
||||
public VirtualDeviceParams[] newArray(int size) {
|
||||
return new VirtualDeviceParams[size];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Builder for {@link VirtualDeviceParams}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
|
||||
private @LockState int mLockState = LOCK_STATE_ALWAYS_LOCKED;
|
||||
|
||||
/**
|
||||
* Sets the lock state of the device. The permission {@code ADD_ALWAYS_UNLOCKED_DISPLAY}
|
||||
* is required if this is set to {@link #LOCK_STATE_ALWAYS_UNLOCKED}.
|
||||
* The default is {@link #LOCK_STATE_ALWAYS_LOCKED}.
|
||||
*
|
||||
* @param lockState The lock state, either {@link #LOCK_STATE_ALWAYS_LOCKED} or
|
||||
* {@link #LOCK_STATE_ALWAYS_UNLOCKED}.
|
||||
*/
|
||||
@RequiresPermission(value = ADD_ALWAYS_UNLOCKED_DISPLAY, conditional = true)
|
||||
@NonNull
|
||||
public Builder setLockState(@LockState int lockState) {
|
||||
mLockState = lockState;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link VirtualDeviceParams} instance.
|
||||
*/
|
||||
@NonNull
|
||||
public VirtualDeviceParams build() {
|
||||
return new VirtualDeviceParams(mLockState);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,8 +22,10 @@ import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTE
|
||||
import android.annotation.NonNull;
|
||||
import android.companion.AssociationInfo;
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.hardware.input.VirtualKeyEvent;
|
||||
import android.hardware.input.VirtualMouseButtonEvent;
|
||||
import android.hardware.input.VirtualMouseRelativeEvent;
|
||||
@@ -56,6 +58,7 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
final List<Integer> mVirtualDisplayIds = new ArrayList<>();
|
||||
private final OnDeviceCloseListener mListener;
|
||||
private final IBinder mAppToken;
|
||||
private final VirtualDeviceParams mParams;
|
||||
|
||||
/**
|
||||
* A mapping from the virtual display ID to its corresponding
|
||||
@@ -65,17 +68,21 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
new SparseArray<>();
|
||||
|
||||
VirtualDeviceImpl(Context context, AssociationInfo associationInfo,
|
||||
IBinder token, int ownerUid, OnDeviceCloseListener listener) {
|
||||
this(context, associationInfo, token, ownerUid, /* inputController= */ null, listener);
|
||||
IBinder token, int ownerUid, OnDeviceCloseListener listener,
|
||||
VirtualDeviceParams params) {
|
||||
this(context, associationInfo, token, ownerUid, /* inputController= */ null, listener,
|
||||
params);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
VirtualDeviceImpl(Context context, AssociationInfo associationInfo, IBinder token,
|
||||
int ownerUid, InputController inputController, OnDeviceCloseListener listener) {
|
||||
int ownerUid, InputController inputController, OnDeviceCloseListener listener,
|
||||
VirtualDeviceParams params) {
|
||||
mContext = context;
|
||||
mAssociationInfo = associationInfo;
|
||||
mOwnerUid = ownerUid;
|
||||
mAppToken = token;
|
||||
mParams = params;
|
||||
if (inputController == null) {
|
||||
mInputController = new InputController(mVirtualDeviceLock);
|
||||
} else {
|
||||
@@ -89,7 +96,19 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* Returns the flags that should be added to any virtual displays created on this virtual
|
||||
* device.
|
||||
*/
|
||||
int getBaseVirtualDisplayFlags() {
|
||||
int flags = 0;
|
||||
if (mParams.getLockState() == VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED) {
|
||||
flags |= DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public int getAssociationId() {
|
||||
return mAssociationInfo.getId();
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.companion.CompanionDeviceManager;
|
||||
import android.companion.CompanionDeviceManager.OnAssociationsChangedListener;
|
||||
import android.companion.virtual.IVirtualDevice;
|
||||
import android.companion.virtual.IVirtualDeviceManager;
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
import android.content.Context;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
@@ -131,7 +132,10 @@ public class VirtualDeviceManagerService extends SystemService {
|
||||
|
||||
@Override // Binder call
|
||||
public IVirtualDevice createVirtualDevice(
|
||||
IBinder token, String packageName, int associationId) {
|
||||
IBinder token,
|
||||
String packageName,
|
||||
int associationId,
|
||||
@NonNull VirtualDeviceParams params) {
|
||||
getContext().enforceCallingOrSelfPermission(
|
||||
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
|
||||
"createVirtualDevice");
|
||||
@@ -160,7 +164,7 @@ public class VirtualDeviceManagerService extends SystemService {
|
||||
mVirtualDevices.remove(associationId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, params);
|
||||
mVirtualDevices.put(associationInfo.getId(), virtualDevice);
|
||||
return virtualDevice;
|
||||
}
|
||||
@@ -237,6 +241,11 @@ public class VirtualDeviceManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBaseVirtualDisplayFlags(IVirtualDevice virtualDevice) {
|
||||
return ((VirtualDeviceImpl) virtualDevice).getBaseVirtualDisplayFlags();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAppOwnerOfAnyVirtualDevice(int uid) {
|
||||
synchronized (mVirtualDeviceManagerLock) {
|
||||
|
||||
@@ -49,6 +49,12 @@ public abstract class VirtualDeviceManagerInternal {
|
||||
*/
|
||||
public abstract void onVirtualDisplayRemoved(IVirtualDevice virtualDevice, int displayId);
|
||||
|
||||
/**
|
||||
* Returns the flags that should be added to any virtual displays created on this virtual
|
||||
* device.
|
||||
*/
|
||||
public abstract int getBaseVirtualDisplayFlags(IVirtualDevice virtualDevice);
|
||||
|
||||
/**
|
||||
* Returns true if the given {@code uid} is the owner of any virtual devices that are
|
||||
* currently active.
|
||||
|
||||
@@ -1251,6 +1251,14 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
final Surface surface = virtualDisplayConfig.getSurface();
|
||||
int flags = virtualDisplayConfig.getFlags();
|
||||
if (virtualDevice != null) {
|
||||
final VirtualDeviceManagerInternal vdm =
|
||||
getLocalService(VirtualDeviceManagerInternal.class);
|
||||
if (!vdm.isValidVirtualDevice(virtualDevice)) {
|
||||
throw new SecurityException("Invalid virtual device");
|
||||
}
|
||||
flags |= vdm.getBaseVirtualDisplayFlags(virtualDevice);
|
||||
}
|
||||
|
||||
if (surface != null && surface.isSingleBuffered()) {
|
||||
throw new IllegalArgumentException("Surface can't be single-buffered");
|
||||
@@ -1283,14 +1291,6 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
if (virtualDevice != null) {
|
||||
final VirtualDeviceManagerInternal vdm =
|
||||
getLocalService(VirtualDeviceManagerInternal.class);
|
||||
if (!vdm.isValidVirtualDevice(virtualDevice)) {
|
||||
throw new SecurityException("Invalid virtual device");
|
||||
}
|
||||
}
|
||||
|
||||
if (callingUid != Process.SYSTEM_UID
|
||||
&& (flags & VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR) != 0) {
|
||||
if (!canProjectVideo(projection)) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.testng.Assert.assertThrows;
|
||||
|
||||
import android.Manifest;
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
import android.content.Context;
|
||||
import android.content.ContextWrapper;
|
||||
import android.graphics.Point;
|
||||
@@ -84,7 +85,7 @@ public class VirtualDeviceManagerServiceTest {
|
||||
mInputController = new InputController(new Object(), mNativeWrapperMock);
|
||||
mDeviceImpl = new VirtualDeviceImpl(mContext,
|
||||
/* association info */ null, new Binder(), /* uid */ 0, mInputController,
|
||||
(int associationId) -> {});
|
||||
(int associationId) -> {}, new VirtualDeviceParams.Builder().build());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.server.companion.virtual;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.companion.virtual.VirtualDeviceParams;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class VirtualDeviceParamsTest {
|
||||
|
||||
@Test
|
||||
public void parcelable_shouldRecreateSuccessfully() {
|
||||
VirtualDeviceParams originalParams = new VirtualDeviceParams.Builder().setLockState(
|
||||
VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED).build();
|
||||
Parcel parcel = Parcel.obtain();
|
||||
originalParams.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
|
||||
VirtualDeviceParams params = VirtualDeviceParams.CREATOR.createFromParcel(parcel);
|
||||
assertThat(params).isEqualTo(originalParams);
|
||||
assertThat(params.getLockState()).isEqualTo(VirtualDeviceParams.LOCK_STATE_ALWAYS_UNLOCKED);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user