Merge "Use VirtualInputDeviceConfig subclasses to create virtual input devices."

This commit is contained in:
Zixuan Qu
2022-12-06 03:41:48 +00:00
committed by Android (Google) Code Review
15 changed files with 928 additions and 206 deletions

View File

@@ -2988,10 +2988,13 @@ package android.companion.virtual {
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.companion.virtual.audio.VirtualAudioDevice createVirtualAudioDevice(@NonNull android.hardware.display.VirtualDisplay, @Nullable java.util.concurrent.Executor, @Nullable android.companion.virtual.audio.VirtualAudioDevice.AudioConfigurationChangeCallback);
method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
method @Nullable public android.hardware.display.VirtualDisplay createVirtualDisplay(@IntRange(from=1) int, @IntRange(from=1) int, @IntRange(from=1) int, @NonNull java.util.List<java.lang.String>, @Nullable android.view.Surface, int, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.display.VirtualDisplay.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualDpad createVirtualDpad(@NonNull android.hardware.input.VirtualDpadConfig);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.input.VirtualKeyboardConfig);
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualKeyboard createVirtualKeyboard(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.input.VirtualMouseConfig);
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualMouse createVirtualMouse(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.input.VirtualTouchscreenConfig);
method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.hardware.input.VirtualTouchscreen createVirtualTouchscreen(@NonNull android.hardware.display.VirtualDisplay, @NonNull String, int, int);
method public int getDeviceId();
method @Nullable public android.companion.virtual.sensor.VirtualSensor getVirtualSensor(int, @NonNull String);
method public void launchPendingIntent(int, @NonNull android.app.PendingIntent, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.IntConsumer);
@@ -4638,6 +4641,34 @@ package android.hardware.input {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void sendKeyEvent(@NonNull android.hardware.input.VirtualKeyEvent);
}
public final class VirtualDpadConfig extends android.hardware.input.VirtualInputDeviceConfig implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.VirtualDpadConfig> CREATOR;
}
public static final class VirtualDpadConfig.Builder extends android.hardware.input.VirtualInputDeviceConfig.Builder<android.hardware.input.VirtualDpadConfig.Builder> {
ctor public VirtualDpadConfig.Builder();
method @NonNull public android.hardware.input.VirtualDpadConfig build();
}
public abstract class VirtualInputDeviceConfig {
ctor protected VirtualInputDeviceConfig(@NonNull android.hardware.input.VirtualInputDeviceConfig.Builder<? extends android.hardware.input.VirtualInputDeviceConfig.Builder<?>>);
ctor protected VirtualInputDeviceConfig(@NonNull android.os.Parcel);
method public int getAssociatedDisplayId();
method @NonNull public String getInputDeviceName();
method public int getProductId();
method public int getVendorId();
}
public abstract static class VirtualInputDeviceConfig.Builder<T extends android.hardware.input.VirtualInputDeviceConfig.Builder<T>> {
ctor public VirtualInputDeviceConfig.Builder();
method @NonNull public T setAssociatedDisplayId(int);
method @NonNull public T setInputDeviceName(@NonNull String);
method @NonNull public T setProductId(int);
method @NonNull public T setVendorId(int);
}
public final class VirtualKeyEvent implements android.os.Parcelable {
method public int describeContents();
method public int getAction();
@@ -4660,6 +4691,17 @@ package android.hardware.input {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void sendKeyEvent(@NonNull android.hardware.input.VirtualKeyEvent);
}
public final class VirtualKeyboardConfig extends android.hardware.input.VirtualInputDeviceConfig implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.VirtualKeyboardConfig> CREATOR;
}
public static final class VirtualKeyboardConfig.Builder extends android.hardware.input.VirtualInputDeviceConfig.Builder<android.hardware.input.VirtualKeyboardConfig.Builder> {
ctor public VirtualKeyboardConfig.Builder();
method @NonNull public android.hardware.input.VirtualKeyboardConfig build();
}
public class VirtualMouse implements java.io.Closeable {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void close();
method @NonNull @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public android.graphics.PointF getCursorPosition();
@@ -4690,6 +4732,17 @@ package android.hardware.input {
method @NonNull public android.hardware.input.VirtualMouseButtonEvent.Builder setButtonCode(int);
}
public final class VirtualMouseConfig extends android.hardware.input.VirtualInputDeviceConfig implements android.os.Parcelable {
method public int describeContents();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.VirtualMouseConfig> CREATOR;
}
public static final class VirtualMouseConfig.Builder extends android.hardware.input.VirtualInputDeviceConfig.Builder<android.hardware.input.VirtualMouseConfig.Builder> {
ctor public VirtualMouseConfig.Builder();
method @NonNull public android.hardware.input.VirtualMouseConfig build();
}
public final class VirtualMouseRelativeEvent implements android.os.Parcelable {
method public int describeContents();
method public float getRelativeX();
@@ -4756,6 +4809,21 @@ package android.hardware.input {
method @RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE) public void sendTouchEvent(@NonNull android.hardware.input.VirtualTouchEvent);
}
public final class VirtualTouchscreenConfig extends android.hardware.input.VirtualInputDeviceConfig implements android.os.Parcelable {
method public int describeContents();
method public int getHeightInPixels();
method public int getWidthInPixels();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.hardware.input.VirtualTouchscreenConfig> CREATOR;
}
public static final class VirtualTouchscreenConfig.Builder extends android.hardware.input.VirtualInputDeviceConfig.Builder<android.hardware.input.VirtualTouchscreenConfig.Builder> {
ctor public VirtualTouchscreenConfig.Builder();
method @NonNull public android.hardware.input.VirtualTouchscreenConfig build();
method @NonNull public android.hardware.input.VirtualTouchscreenConfig.Builder setHeightInPixels(int);
method @NonNull public android.hardware.input.VirtualTouchscreenConfig.Builder setWidthInPixels(int);
}
}
package android.hardware.lights {

View File

@@ -24,11 +24,15 @@ import android.companion.virtual.sensor.VirtualSensorConfig;
import android.companion.virtual.sensor.VirtualSensorEvent;
import android.graphics.Point;
import android.graphics.PointF;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyboardConfig;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualMouseButtonEvent;
import android.hardware.input.VirtualMouseConfig;
import android.hardware.input.VirtualMouseRelativeEvent;
import android.hardware.input.VirtualMouseScrollEvent;
import android.hardware.input.VirtualTouchEvent;
import android.hardware.input.VirtualTouchscreenConfig;
import android.os.ResultReceiver;
/**
@@ -64,32 +68,22 @@ interface IVirtualDevice {
IAudioConfigChangedCallback configChangedCallback);
void onAudioSessionEnded();
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)")
void createVirtualDpad(
int displayId,
String inputDeviceName,
int vendorId,
int productId,
in VirtualDpadConfig config,
IBinder token);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)")
void createVirtualKeyboard(
int displayId,
String inputDeviceName,
int vendorId,
int productId,
in VirtualKeyboardConfig config,
IBinder token);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)")
void createVirtualMouse(
int displayId,
String inputDeviceName,
int vendorId,
int productId,
in VirtualMouseConfig config,
IBinder token);
@JavaPassthrough(annotation="@android.annotation.RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)")
void createVirtualTouchscreen(
int displayId,
String inputDeviceName,
int vendorId,
int productId,
IBinder token,
in Point screenSize);
in VirtualTouchscreenConfig config,
IBinder token);
void unregisterInputDevice(IBinder token);
int getInputDeviceId(IBinder token);
boolean sendDpadKeyEvent(IBinder token, in VirtualKeyEvent event);

View File

@@ -41,9 +41,13 @@ import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplay;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.VirtualDpad;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyboard;
import android.hardware.input.VirtualKeyboardConfig;
import android.hardware.input.VirtualMouse;
import android.hardware.input.VirtualMouseConfig;
import android.hardware.input.VirtualTouchscreen;
import android.hardware.input.VirtualTouchscreenConfig;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
@@ -512,23 +516,15 @@ public final class VirtualDeviceManager {
/**
* Creates a virtual dpad.
*
* @param display the display that the events inputted through this device should target
* @param inputDeviceName the name to call this input device
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @param config the configurations of the virtual Dpad.
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualDpad createVirtualDpad(
@NonNull VirtualDisplay display,
@NonNull String inputDeviceName,
int vendorId,
int productId) {
public VirtualDpad createVirtualDpad(@NonNull VirtualDpadConfig config) {
try {
final IBinder token = new Binder(
"android.hardware.input.VirtualDpad:" + inputDeviceName);
mVirtualDevice.createVirtualDpad(display.getDisplay().getDisplayId(),
inputDeviceName, vendorId, productId, token);
"android.hardware.input.VirtualDpad:" + config.getInputDeviceName());
mVirtualDevice.createVirtualDpad(config, token);
return new VirtualDpad(mVirtualDevice, token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -538,50 +534,106 @@ public final class VirtualDeviceManager {
/**
* Creates a virtual keyboard.
*
* @param display the display that the events inputted through this device should target
* @param inputDeviceName the name to call this input device
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @param config the configurations of the virtual keyboard.
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualKeyboard createVirtualKeyboard(
@NonNull VirtualDisplay display,
@NonNull String inputDeviceName,
int vendorId,
int productId) {
public VirtualKeyboard createVirtualKeyboard(@NonNull VirtualKeyboardConfig config) {
try {
final IBinder token = new Binder(
"android.hardware.input.VirtualKeyboard:" + inputDeviceName);
mVirtualDevice.createVirtualKeyboard(display.getDisplay().getDisplayId(),
inputDeviceName, vendorId, productId, token);
"android.hardware.input.VirtualKeyboard:" + config.getInputDeviceName());
mVirtualDevice.createVirtualKeyboard(config, token);
return new VirtualKeyboard(mVirtualDevice, token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Creates a virtual keyboard.
*
* @param display the display that the events inputted through this device should
* target
* @param inputDeviceName the name to call this input device
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @see #createVirtualKeyboard(VirtualKeyboardConfig config)
* @deprecated Use {@link #createVirtualKeyboard(VirtualKeyboardConfig config)} instead
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualKeyboard createVirtualKeyboard(@NonNull VirtualDisplay display,
@NonNull String inputDeviceName, int vendorId, int productId) {
VirtualKeyboardConfig keyboardConfig =
new VirtualKeyboardConfig.Builder()
.setVendorId(vendorId)
.setProductId(productId)
.setInputDeviceName(inputDeviceName)
.setAssociatedDisplayId(display.getDisplay().getDisplayId())
.build();
return createVirtualKeyboard(keyboardConfig);
}
/**
* Creates a virtual mouse.
*
* @param config the configurations of the virtual mouse.
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualMouse createVirtualMouse(@NonNull VirtualMouseConfig config) {
try {
final IBinder token = new Binder(
"android.hardware.input.VirtualMouse:" + config.getInputDeviceName());
mVirtualDevice.createVirtualMouse(config, token);
return new VirtualMouse(mVirtualDevice, token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Creates a virtual mouse.
*
* @param display the display that the events inputted through this device should target
* @param display the display that the events inputted through this device should
* target
* @param inputDeviceName the name to call this input device
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @see #createVirtualMouse(VirtualMouseConfig config)
* @deprecated Use {@link #createVirtualMouse(VirtualMouseConfig config)} instead
* *
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualMouse createVirtualMouse(@NonNull VirtualDisplay display,
@NonNull String inputDeviceName, int vendorId, int productId) {
VirtualMouseConfig mouseConfig =
new VirtualMouseConfig.Builder()
.setVendorId(vendorId)
.setProductId(productId)
.setInputDeviceName(inputDeviceName)
.setAssociatedDisplayId(display.getDisplay().getDisplayId())
.build();
return createVirtualMouse(mouseConfig);
}
/**
* Creates a virtual touchscreen.
*
* @param config the configurations of the virtual touchscreen.
*/
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualMouse createVirtualMouse(
@NonNull VirtualDisplay display,
@NonNull String inputDeviceName,
int vendorId,
int productId) {
public VirtualTouchscreen createVirtualTouchscreen(
@NonNull VirtualTouchscreenConfig config) {
try {
final IBinder token = new Binder(
"android.hardware.input.VirtualMouse:" + inputDeviceName);
mVirtualDevice.createVirtualMouse(display.getDisplay().getDisplayId(),
inputDeviceName, vendorId, productId, token);
return new VirtualMouse(mVirtualDevice, token);
"android.hardware.input.VirtualTouchscreen:" + config.getInputDeviceName());
mVirtualDevice.createVirtualTouchscreen(config, token);
return new VirtualTouchscreen(mVirtualDevice, token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -590,29 +642,32 @@ public final class VirtualDeviceManager {
/**
* Creates a virtual touchscreen.
*
* @param display the display that the events inputted through this device should target
* @param display the display that the events inputted through this device should
* target
* @param inputDeviceName the name to call this input device
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @param vendorId the PCI vendor id
* @param productId the product id, as defined by the vendor
* @see #createVirtualTouchscreen(VirtualTouchscreenConfig config)
* @deprecated Use {@link #createVirtualTouchscreen(VirtualTouchscreenConfig config)}
* instead
*/
@Deprecated
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@NonNull
public VirtualTouchscreen createVirtualTouchscreen(
@NonNull VirtualDisplay display,
@NonNull String inputDeviceName,
int vendorId,
int productId) {
try {
final IBinder token = new Binder(
"android.hardware.input.VirtualTouchscreen:" + inputDeviceName);
final Point size = new Point();
display.getDisplay().getSize(size);
mVirtualDevice.createVirtualTouchscreen(display.getDisplay().getDisplayId(),
inputDeviceName, vendorId, productId, token, size);
return new VirtualTouchscreen(mVirtualDevice, token);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
public VirtualTouchscreen createVirtualTouchscreen(@NonNull VirtualDisplay display,
@NonNull String inputDeviceName, int vendorId, int productId) {
final Point size = new Point();
display.getDisplay().getSize(size);
VirtualTouchscreenConfig touchscreenConfig =
new VirtualTouchscreenConfig.Builder()
.setVendorId(vendorId)
.setProductId(productId)
.setInputDeviceName(inputDeviceName)
.setAssociatedDisplayId(display.getDisplay().getDisplayId())
.setWidthInPixels(size.x)
.setHeightInPixels(size.y)
.build();
return createVirtualTouchscreen(touchscreenConfig);
}
/**

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2022 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.hardware.input;
parcelable VirtualDpadConfig;

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 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.hardware.input;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Configurations to create virtual Dpad.
*
* @hide
*/
@SystemApi
public final class VirtualDpadConfig extends VirtualInputDeviceConfig implements Parcelable {
@NonNull
public static final Creator<VirtualDpadConfig> CREATOR = new Creator<VirtualDpadConfig>() {
@Override
public VirtualDpadConfig createFromParcel(Parcel in) {
return new VirtualDpadConfig(in);
}
@Override
public VirtualDpadConfig[] newArray(int size) {
return new VirtualDpadConfig[size];
}
};
private VirtualDpadConfig(@NonNull VirtualDpadConfig.Builder builder) {
super(builder);
}
private VirtualDpadConfig(@NonNull Parcel in) {
super(in);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
/**
* Builder for creating a {@link VirtualDpadConfig}.
*/
public static final class Builder extends VirtualInputDeviceConfig.Builder<Builder> {
/**
* Builds the {@link VirtualDpadConfig} instance.
*/
@NonNull
public VirtualDpadConfig build() {
return new VirtualDpadConfig(this);
}
}
}

View File

@@ -0,0 +1,144 @@
/*
* Copyright (C) 2022 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.hardware.input;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
/**
* Common configurations to create virtual input devices.
*
* @hide
*/
@SystemApi
public abstract class VirtualInputDeviceConfig {
/** The vendor id uniquely identifies the company who manufactured the device. */
private final int mVendorId;
/**
* The product id uniquely identifies which product within the address space of a given vendor,
* identified by the device's vendor id.
*/
private final int mProductId;
/** The associated display ID of the virtual input device. */
private final int mAssociatedDisplayId;
/** The name of the virtual input device. */
@NonNull
private final String mInputDeviceName;
protected VirtualInputDeviceConfig(@NonNull Builder<? extends Builder<?>> builder) {
mVendorId = builder.mVendorId;
mProductId = builder.mProductId;
mAssociatedDisplayId = builder.mAssociatedDisplayId;
mInputDeviceName = builder.mInputDeviceName;
}
protected VirtualInputDeviceConfig(@NonNull Parcel in) {
mVendorId = in.readInt();
mProductId = in.readInt();
mAssociatedDisplayId = in.readInt();
mInputDeviceName = in.readString8();
}
/**
* The vendor id uniquely identifies the company who manufactured the device.
*/
public int getVendorId() {
return mVendorId;
}
/**
* The product id uniquely identifies which product within the address space of a given vendor,
* identified by the device's vendor id.
*/
public int getProductId() {
return mProductId;
}
/**
* The associated display ID of the virtual input device.
*/
public int getAssociatedDisplayId() {
return mAssociatedDisplayId;
}
/**
* The name of the virtual input device.
*/
@NonNull
public String getInputDeviceName() {
return mInputDeviceName;
}
void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(mVendorId);
dest.writeInt(mProductId);
dest.writeInt(mAssociatedDisplayId);
dest.writeString8(mInputDeviceName);
}
/**
* A builder for {@link VirtualInputDeviceConfig}
*
* @param <T> The subclass to be built.
*/
@SuppressWarnings({"StaticFinalBuilder", "MissingBuildMethod"})
public abstract static class Builder<T extends Builder<T>> {
private int mVendorId;
private int mProductId;
private int mAssociatedDisplayId;
@NonNull
private String mInputDeviceName;
/** @see VirtualInputDeviceConfig#getVendorId(). */
@NonNull
public T setVendorId(int vendorId) {
mVendorId = vendorId;
return self();
}
/** @see VirtualInputDeviceConfig#getProductId(). */
@NonNull
public T setProductId(int productId) {
mProductId = productId;
return self();
}
/** @see VirtualInputDeviceConfig#getAssociatedDisplayId(). */
@NonNull
public T setAssociatedDisplayId(int displayId) {
mAssociatedDisplayId = displayId;
return self();
}
/** @see VirtualInputDeviceConfig#getInputDeviceName(). */
@NonNull
public T setInputDeviceName(@NonNull String deviceName) {
mInputDeviceName = deviceName;
return self();
}
/**
* Each subclass should return itself to allow the builder to chain properly
*/
T self() {
return (T) this;
}
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2022 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.hardware.input;
parcelable VirtualKeyboardConfig;

View File

@@ -0,0 +1,77 @@
/*
* Copyright (C) 2022 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.hardware.input;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Configurations to create virtual keyboard.
*
* @hide
*/
@SystemApi
public final class VirtualKeyboardConfig extends VirtualInputDeviceConfig implements Parcelable {
@NonNull
public static final Creator<VirtualKeyboardConfig> CREATOR =
new Creator<VirtualKeyboardConfig>() {
@Override
public VirtualKeyboardConfig createFromParcel(Parcel in) {
return new VirtualKeyboardConfig(in);
}
@Override
public VirtualKeyboardConfig[] newArray(int size) {
return new VirtualKeyboardConfig[size];
}
};
private VirtualKeyboardConfig(@NonNull Builder builder) {
super(builder);
}
private VirtualKeyboardConfig(@NonNull Parcel in) {
super(in);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
/**
* Builder for creating a {@link VirtualKeyboardConfig}.
*/
public static final class Builder extends VirtualInputDeviceConfig.Builder<Builder> {
/**
* Builds the {@link VirtualKeyboardConfig} instance.
*/
@NonNull
public VirtualKeyboardConfig build() {
return new VirtualKeyboardConfig(this);
}
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2022 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.hardware.input;
parcelable VirtualMouseConfig;

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2022 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.hardware.input;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Configurations to create virtual mouse.
*
* @hide
*/
@SystemApi
public final class VirtualMouseConfig extends VirtualInputDeviceConfig implements Parcelable {
@NonNull
public static final Creator<VirtualMouseConfig> CREATOR = new Creator<VirtualMouseConfig>() {
@Override
public VirtualMouseConfig createFromParcel(Parcel in) {
return new VirtualMouseConfig(in);
}
@Override
public VirtualMouseConfig[] newArray(int size) {
return new VirtualMouseConfig[size];
}
};
private VirtualMouseConfig(@NonNull VirtualMouseConfig.Builder builder) {
super(builder);
}
private VirtualMouseConfig(@NonNull Parcel in) {
super(in);
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
}
/**
* Builder for creating a {@link VirtualMouseConfig}.
*/
public static final class Builder extends VirtualInputDeviceConfig.Builder<Builder> {
/**
* Builds the {@link VirtualMouseConfig} instance.
*/
@NonNull
public VirtualMouseConfig build() {
return new VirtualMouseConfig(this);
}
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright (C) 2022 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.hardware.input;
parcelable VirtualTouchscreenConfig;

View File

@@ -0,0 +1,118 @@
/*
* Copyright (C) 2022 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.hardware.input;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
/**
* Configurations to create virtual touchscreen.
*
* @hide
*/
@SystemApi
public final class VirtualTouchscreenConfig extends VirtualInputDeviceConfig implements Parcelable {
/** The touchscreen width in pixels. */
private final int mWidthInPixels;
/** The touchscreen height in pixels. */
private final int mHeightInPixels;
private VirtualTouchscreenConfig(@NonNull Builder builder) {
super(builder);
mWidthInPixels = builder.mWidthInPixels;
mHeightInPixels = builder.mHeightInPixels;
}
private VirtualTouchscreenConfig(@NonNull Parcel in) {
super(in);
mWidthInPixels = in.readInt();
mHeightInPixels = in.readInt();
}
/** Returns the touchscreen width in pixels. */
public int getWidthInPixels() {
return mWidthInPixels;
}
/** Returns the touchscreen height in pixels. */
public int getHeightInPixels() {
return mHeightInPixels;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(mWidthInPixels);
dest.writeInt(mHeightInPixels);
}
@NonNull
public static final Creator<VirtualTouchscreenConfig> CREATOR =
new Creator<VirtualTouchscreenConfig>() {
@Override
public VirtualTouchscreenConfig createFromParcel(Parcel in) {
return new VirtualTouchscreenConfig(in);
}
@Override
public VirtualTouchscreenConfig[] newArray(int size) {
return new VirtualTouchscreenConfig[size];
}
};
/**
* Builder for creating a {@link VirtualTouchscreenConfig}.
*/
public static final class Builder extends VirtualInputDeviceConfig.Builder<Builder> {
private int mWidthInPixels;
private int mHeightInPixels;
/**
* @see VirtualTouchscreenConfig#getWidthInPixels().
*/
@NonNull
public Builder setWidthInPixels(int widthInPixels) {
mWidthInPixels = widthInPixels;
return this;
}
/**
* @see VirtualTouchscreenConfig#getHeightInPixels().
*/
@NonNull
public Builder setHeightInPixels(int heightInPixels) {
mHeightInPixels = heightInPixels;
return this;
}
/**
* Builds the {@link VirtualTouchscreenConfig} instance.
*/
@NonNull
public VirtualTouchscreenConfig build() {
return new VirtualTouchscreenConfig(this);
}
}
}

View File

@@ -19,7 +19,6 @@ package com.android.server.companion.virtual;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.StringDef;
import android.graphics.Point;
import android.graphics.PointF;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.InputDeviceIdentifier;
@@ -178,13 +177,14 @@ class InputController {
int productId,
@NonNull IBinder deviceToken,
int displayId,
@NonNull Point screenSize) {
int height,
int width) {
final String phys = createPhys(PHYS_TYPE_TOUCHSCREEN);
try {
createDeviceInternal(InputDeviceDescriptor.TYPE_TOUCHSCREEN, deviceName, vendorId,
productId, deviceToken, displayId, phys,
() -> mNativeWrapper.openUinputTouchscreen(deviceName, vendorId, productId,
phys, screenSize.y, screenSize.x));
phys, height, width));
} catch (DeviceCreationException e) {
throw new RuntimeException(
"Failed to create virtual touchscreen device '" + deviceName + "'.", e);
@@ -414,17 +414,25 @@ class InputController {
}
@VisibleForTesting
void addDeviceForTesting(IBinder deviceToken, int fd, int type, int displayId,
String phys, int inputDeviceId) {
void addDeviceForTesting(IBinder deviceToken, int fd, int type, int displayId, String phys,
int inputDeviceId) {
synchronized (mLock) {
mInputDeviceDescriptors.put(deviceToken,
new InputDeviceDescriptor(fd, () -> {}, type, displayId, phys,
inputDeviceId));
mInputDeviceDescriptors.put(deviceToken, new InputDeviceDescriptor(fd, () -> {
}, type, displayId, phys, inputDeviceId));
}
}
private static native int nativeOpenUinputDpad(String deviceName, int vendorId,
int productId, String phys);
@VisibleForTesting
Map<IBinder, InputDeviceDescriptor> getInputDeviceDescriptors() {
final Map<IBinder, InputDeviceDescriptor> inputDeviceDescriptors = new ArrayMap<>();
synchronized (mLock) {
inputDeviceDescriptors.putAll(mInputDeviceDescriptors);
}
return inputDeviceDescriptors;
}
private static native int nativeOpenUinputDpad(String deviceName, int vendorId, int productId,
String phys);
private static native int nativeOpenUinputKeyboard(String deviceName, int vendorId,
int productId, String phys);
private static native int nativeOpenUinputMouse(String deviceName, int vendorId, int productId,

View File

@@ -44,14 +44,17 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Point;
import android.graphics.PointF;
import android.hardware.display.DisplayManager;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualKeyboardConfig;
import android.hardware.input.VirtualMouseButtonEvent;
import android.hardware.input.VirtualMouseConfig;
import android.hardware.input.VirtualMouseRelativeEvent;
import android.hardware.input.VirtualMouseScrollEvent;
import android.hardware.input.VirtualTouchEvent;
import android.hardware.input.VirtualTouchscreenConfig;
import android.os.Binder;
import android.os.IBinder;
import android.os.Looper;
@@ -397,19 +400,12 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
}
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override // Binder call
public void createVirtualDpad(
int displayId,
@NonNull String deviceName,
int vendorId,
int productId,
@NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
public void createVirtualDpad(VirtualDpadConfig config, @NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"Permission required to create a virtual dpad");
synchronized (mVirtualDeviceLock) {
if (!mVirtualDisplayIds.contains(displayId)) {
if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual dpad for a display not associated with "
+ "this virtual device");
@@ -417,26 +413,19 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
final long ident = Binder.clearCallingIdentity();
try {
mInputController.createDpad(deviceName, vendorId, productId, deviceToken,
displayId);
mInputController.createDpad(config.getInputDeviceName(), config.getVendorId(),
config.getProductId(), deviceToken, config.getAssociatedDisplayId());
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override // Binder call
public void createVirtualKeyboard(
int displayId,
@NonNull String deviceName,
int vendorId,
int productId,
@NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
public void createVirtualKeyboard(VirtualKeyboardConfig config, @NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"Permission required to create a virtual keyboard");
synchronized (mVirtualDeviceLock) {
if (!mVirtualDisplayIds.contains(displayId)) {
if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual keyboard for a display not associated with "
+ "this virtual device");
@@ -444,26 +433,19 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
final long ident = Binder.clearCallingIdentity();
try {
mInputController.createKeyboard(deviceName, vendorId, productId, deviceToken,
displayId);
mInputController.createKeyboard(config.getInputDeviceName(), config.getVendorId(),
config.getProductId(), deviceToken, config.getAssociatedDisplayId());
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override // Binder call
public void createVirtualMouse(
int displayId,
@NonNull String deviceName,
int vendorId,
int productId,
@NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
public void createVirtualMouse(VirtualMouseConfig config, @NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"Permission required to create a virtual mouse");
synchronized (mVirtualDeviceLock) {
if (!mVirtualDisplayIds.contains(displayId)) {
if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual mouse for a display not associated with this "
+ "virtual device");
@@ -471,42 +453,38 @@ final class VirtualDeviceImpl extends IVirtualDevice.Stub
}
final long ident = Binder.clearCallingIdentity();
try {
mInputController.createMouse(deviceName, vendorId, productId, deviceToken, displayId);
mInputController.createMouse(config.getInputDeviceName(), config.getVendorId(),
config.getProductId(), deviceToken, config.getAssociatedDisplayId());
} finally {
Binder.restoreCallingIdentity(ident);
}
}
@RequiresPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE)
@Override // Binder call
public void createVirtualTouchscreen(
int displayId,
@NonNull String deviceName,
int vendorId,
int productId,
@NonNull IBinder deviceToken,
@NonNull Point screenSize) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
public void createVirtualTouchscreen(VirtualTouchscreenConfig config,
@NonNull IBinder deviceToken) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CREATE_VIRTUAL_DEVICE,
"Permission required to create a virtual touchscreen");
synchronized (mVirtualDeviceLock) {
if (!mVirtualDisplayIds.contains(displayId)) {
if (!mVirtualDisplayIds.contains(config.getAssociatedDisplayId())) {
throw new SecurityException(
"Cannot create a virtual touchscreen for a display not associated with "
+ "this virtual device");
}
}
if (screenSize.x <= 0 || screenSize.y <= 0) {
int screenHeightPixels = config.getHeightInPixels();
int screenWidthPixels = config.getWidthInPixels();
if (screenHeightPixels <= 0 || screenWidthPixels <= 0) {
throw new IllegalArgumentException(
"Cannot create a virtual touchscreen, screen dimensions must be positive. Got: "
+ screenSize);
+ "(" + screenWidthPixels + ", " + screenHeightPixels + ")");
}
final long ident = Binder.clearCallingIdentity();
try {
mInputController.createTouchscreen(deviceName, vendorId, productId,
deviceToken, displayId, screenSize);
mInputController.createTouchscreen(config.getInputDeviceName(), config.getVendorId(),
config.getProductId(), deviceToken, config.getAssociatedDisplayId(),
screenHeightPixels, screenWidthPixels);
} finally {
Binder.restoreCallingIdentity(ident);
}

View File

@@ -58,15 +58,18 @@ import android.content.ContextWrapper;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.graphics.Point;
import android.hardware.Sensor;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.input.IInputManager;
import android.hardware.input.VirtualDpadConfig;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualKeyboardConfig;
import android.hardware.input.VirtualMouseButtonEvent;
import android.hardware.input.VirtualMouseConfig;
import android.hardware.input.VirtualMouseRelativeEvent;
import android.hardware.input.VirtualMouseScrollEvent;
import android.hardware.input.VirtualTouchEvent;
import android.hardware.input.VirtualTouchscreenConfig;
import android.net.MacAddress;
import android.os.Binder;
import android.os.Handler;
@@ -135,7 +138,37 @@ public class VirtualDeviceManagerServiceTest {
private static final int SENSOR_HANDLE = 64;
private static final Binder BINDER = new Binder("binder");
private static final int FLAG_CANNOT_DISPLAY_ON_REMOTE_DEVICES = 0x00000;
private static final int VIRTUAL_DEVICE_ID = 42;
private static final int VIRTUAL_DEVICE_ID = 42;
private static final VirtualDpadConfig DPAD_CONFIG =
new VirtualDpadConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.build();
private static final VirtualKeyboardConfig KEYBOARD_CONFIG =
new VirtualKeyboardConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.build();
private static final VirtualMouseConfig MOUSE_CONFIG =
new VirtualMouseConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.build();
private static final VirtualTouchscreenConfig TOUCHSCREEN_CONFIG =
new VirtualTouchscreenConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.setWidthInPixels(WIDTH)
.setHeightInPixels(HEIGHT)
.build();
private Context mContext;
private InputManagerMockHelper mInputManagerMockHelper;
@@ -477,63 +510,77 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualDpad_noDisplay_failsSecurityException() {
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualDpad(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER));
}
@Test
public void createVirtualKeyboard_noDisplay_failsSecurityException() {
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualKeyboard(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER));
}
@Test
public void createVirtualMouse_noDisplay_failsSecurityException() {
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualMouse(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER));
}
@Test
public void createVirtualTouchscreen_noDisplay_failsSecurityException() {
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualTouchscreen(DISPLAY_ID, DEVICE_NAME,
VENDOR_ID, PRODUCT_ID, BINDER, new Point(WIDTH, HEIGHT)));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER));
}
@Test
public void createVirtualTouchscreen_zeroDisplayDimension_failsIllegalArgumentException() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
Point size = new Point(0, 0);
final VirtualTouchscreenConfig zeroConfig =
new VirtualTouchscreenConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.setWidthInPixels(0)
.setHeightInPixels(0)
.build();
assertThrows(IllegalArgumentException.class,
() -> mDeviceImpl.createVirtualTouchscreen(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER, size));
() -> mDeviceImpl.createVirtualTouchscreen(zeroConfig, BINDER));
}
@Test
public void createVirtualTouchscreen_negativeDisplayDimension_failsIllegalArgumentException() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
Point size = new Point(-100, -100);
final VirtualTouchscreenConfig negativeConfig =
new VirtualTouchscreenConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.setWidthInPixels(-100)
.setHeightInPixels(-100)
.build();
assertThrows(IllegalArgumentException.class,
() -> mDeviceImpl.createVirtualTouchscreen(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER, size));
() -> mDeviceImpl.createVirtualTouchscreen(negativeConfig, BINDER));
}
@Test
public void createVirtualTouchscreen_positiveDisplayDimension_successful() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
Point size = new Point(600, 800);
mDeviceImpl.createVirtualTouchscreen(DISPLAY_ID, DEVICE_NAME, VENDOR_ID, PRODUCT_ID, BINDER,
size);
VirtualTouchscreenConfig positiveConfig =
new VirtualTouchscreenConfig.Builder()
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.setInputDeviceName(DEVICE_NAME)
.setAssociatedDisplayId(DISPLAY_ID)
.setWidthInPixels(600)
.setHeightInPixels(800)
.build();
mDeviceImpl.createVirtualTouchscreen(positiveConfig, BINDER);
assertWithMessage(
"Virtual touchscreen should create input device descriptor on successful creation.")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
"Virtual touchscreen should create input device descriptor on successful creation"
+ ".").that(mInputController.getInputDeviceDescriptors()).isNotEmpty();
}
@Test
@@ -548,10 +595,8 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
doCallRealMethod().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString());
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualDpad(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER));
}
@Test
@@ -559,10 +604,8 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
doCallRealMethod().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString());
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualKeyboard(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER));
}
@Test
@@ -570,10 +613,8 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
doCallRealMethod().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString());
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualMouse(DISPLAY_ID, DEVICE_NAME, VENDOR_ID,
PRODUCT_ID, BINDER));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER));
}
@Test
@@ -581,10 +622,8 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
doCallRealMethod().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString());
assertThrows(
SecurityException.class,
() -> mDeviceImpl.createVirtualTouchscreen(DISPLAY_ID, DEVICE_NAME,
VENDOR_ID, PRODUCT_ID, BINDER, new Point(WIDTH, HEIGHT)));
assertThrows(SecurityException.class,
() -> mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER));
}
@Test
@@ -619,21 +658,19 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualDpad_hasDisplay_obtainFileDescriptor() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
mDeviceImpl.createVirtualDpad(DISPLAY_ID, DEVICE_NAME, VENDOR_ID, PRODUCT_ID,
BINDER);
assertWithMessage("Virtual dpad should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
verify(mNativeWrapperMock).openUinputDpad(eq(DEVICE_NAME), eq(VENDOR_ID),
eq(PRODUCT_ID), anyString());
mDeviceImpl.createVirtualDpad(DPAD_CONFIG, BINDER);
assertWithMessage("Virtual dpad should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
verify(mNativeWrapperMock).openUinputDpad(eq(DEVICE_NAME), eq(VENDOR_ID), eq(PRODUCT_ID),
anyString());
}
@Test
public void createVirtualKeyboard_hasDisplay_obtainFileDescriptor() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
mDeviceImpl.createVirtualKeyboard(DISPLAY_ID, DEVICE_NAME, VENDOR_ID, PRODUCT_ID,
BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
mDeviceImpl.createVirtualKeyboard(KEYBOARD_CONFIG, BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
verify(mNativeWrapperMock).openUinputKeyboard(eq(DEVICE_NAME), eq(VENDOR_ID),
eq(PRODUCT_ID), anyString());
}
@@ -641,10 +678,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualMouse_hasDisplay_obtainFileDescriptor() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
mDeviceImpl.createVirtualMouse(DISPLAY_ID, DEVICE_NAME, VENDOR_ID, PRODUCT_ID,
BINDER);
assertWithMessage("Virtual mouse should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
mDeviceImpl.createVirtualMouse(MOUSE_CONFIG, BINDER);
assertWithMessage("Virtual mouse should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
verify(mNativeWrapperMock).openUinputMouse(eq(DEVICE_NAME), eq(VENDOR_ID), eq(PRODUCT_ID),
anyString());
}
@@ -652,10 +688,9 @@ public class VirtualDeviceManagerServiceTest {
@Test
public void createVirtualTouchscreen_hasDisplay_obtainFileDescriptor() {
mDeviceImpl.mVirtualDisplayIds.add(DISPLAY_ID);
mDeviceImpl.createVirtualTouchscreen(DISPLAY_ID, DEVICE_NAME, VENDOR_ID, PRODUCT_ID,
BINDER, new Point(WIDTH, HEIGHT));
assertWithMessage("Virtual touchscreen should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
mDeviceImpl.createVirtualTouchscreen(TOUCHSCREEN_CONFIG, BINDER);
assertWithMessage("Virtual touchscreen should register fd when the display matches").that(
mInputController.getInputDeviceDescriptors()).isNotEmpty();
verify(mNativeWrapperMock).openUinputTouchscreen(eq(DEVICE_NAME), eq(VENDOR_ID),
eq(PRODUCT_ID), anyString(), eq(HEIGHT), eq(WIDTH));
}
@@ -909,9 +944,28 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.mVirtualDisplayIds.add(1);
mDeviceImpl.mVirtualDisplayIds.add(2);
mDeviceImpl.mVirtualDisplayIds.add(3);
mDeviceImpl.createVirtualMouse(1, DEVICE_NAME, VENDOR_ID, PRODUCT_ID, BINDER);
mDeviceImpl.createVirtualMouse(2, DEVICE_NAME, VENDOR_ID, PRODUCT_ID, BINDER);
mDeviceImpl.createVirtualMouse(3, DEVICE_NAME, VENDOR_ID, PRODUCT_ID, BINDER);
VirtualMouseConfig config1 = new VirtualMouseConfig.Builder()
.setAssociatedDisplayId(1)
.setInputDeviceName(DEVICE_NAME)
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.build();
VirtualMouseConfig config2 = new VirtualMouseConfig.Builder()
.setAssociatedDisplayId(2)
.setInputDeviceName(DEVICE_NAME)
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.build();
VirtualMouseConfig config3 = new VirtualMouseConfig.Builder()
.setAssociatedDisplayId(3)
.setInputDeviceName(DEVICE_NAME)
.setVendorId(VENDOR_ID)
.setProductId(PRODUCT_ID)
.build();
mDeviceImpl.createVirtualMouse(config1, BINDER);
mDeviceImpl.createVirtualMouse(config2, BINDER);
mDeviceImpl.createVirtualMouse(config3, BINDER);
mDeviceImpl.setShowPointerIcon(false);
verify(mInputManagerInternalMock, times(3)).setPointerIconVisible(eq(false), anyInt());
verify(mInputManagerInternalMock, never()).setPointerIconVisible(eq(true), anyInt());