| /* |
| * 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.view.Display; |
| |
| import java.nio.charset.StandardCharsets; |
| import java.util.Objects; |
| |
| /** |
| * Common configurations to create virtual input devices. |
| * |
| * @hide |
| */ |
| @SystemApi |
| public abstract class VirtualInputDeviceConfig { |
| |
| /** |
| * The maximum length of a device name (in bytes in UTF-8 encoding). |
| * |
| * This limitation comes directly from uinput. |
| * See also UINPUT_MAX_NAME_SIZE in linux/uinput.h |
| */ |
| private static final int DEVICE_NAME_MAX_LENGTH = 80; |
| |
| /** 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 = Objects.requireNonNull(builder.mInputDeviceName); |
| |
| if (mAssociatedDisplayId == Display.INVALID_DISPLAY) { |
| throw new IllegalArgumentException( |
| "Display association is required for virtual input devices."); |
| } |
| |
| // Comparison is greater or equal because the device name must fit into a const char* |
| // including the \0-terminator. Therefore the actual number of bytes that can be used |
| // for device name is DEVICE_NAME_MAX_LENGTH - 1 |
| if (mInputDeviceName.getBytes(StandardCharsets.UTF_8).length >= DEVICE_NAME_MAX_LENGTH) { |
| throw new IllegalArgumentException("Input device name exceeds maximum length of " |
| + DEVICE_NAME_MAX_LENGTH + "bytes: " + mInputDeviceName); |
| } |
| } |
| |
| protected VirtualInputDeviceConfig(@NonNull Parcel in) { |
| mVendorId = in.readInt(); |
| mProductId = in.readInt(); |
| mAssociatedDisplayId = in.readInt(); |
| mInputDeviceName = Objects.requireNonNull(in.readString8()); |
| } |
| |
| /** |
| * The vendor id uniquely identifies the company who manufactured the device. |
| * |
| * @see Builder#setVendorId(int) (int) |
| */ |
| 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. |
| * |
| * @see Builder#setProductId(int) |
| */ |
| public int getProductId() { |
| return mProductId; |
| } |
| |
| /** |
| * The associated display ID of the virtual input device. |
| * |
| * @see Builder#setAssociatedDisplayId(int) |
| */ |
| public int getAssociatedDisplayId() { |
| return mAssociatedDisplayId; |
| } |
| |
| /** |
| * The name of the virtual input device. |
| * |
| * @see Builder#setInputDeviceName(String) |
| */ |
| @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); |
| } |
| |
| @Override |
| public String toString() { |
| return getClass().getName() + "( " |
| + " name=" + mInputDeviceName |
| + " vendorId=" + mVendorId |
| + " productId=" + mProductId |
| + " associatedDisplayId=" + mAssociatedDisplayId |
| + additionalFieldsToString() + ")"; |
| } |
| |
| /** @hide */ |
| @NonNull |
| String additionalFieldsToString() { |
| return ""; |
| } |
| |
| /** |
| * 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 = Display.INVALID_DISPLAY; |
| private String mInputDeviceName; |
| |
| /** |
| * Sets the vendor id of the device, identifying the company who manufactured the device. |
| */ |
| @NonNull |
| public T setVendorId(int vendorId) { |
| mVendorId = vendorId; |
| return self(); |
| } |
| |
| |
| /** |
| * Sets the product id of the device, uniquely identifying the device within the address |
| * space of a given vendor, identified by the device's vendor id. |
| */ |
| @NonNull |
| public T setProductId(int productId) { |
| mProductId = productId; |
| return self(); |
| } |
| |
| /** |
| * Sets the associated display ID of the virtual input device. Required. |
| * |
| * <p>The input device is restricted to the display with the given ID and may not send |
| * events to any other display.</p> |
| */ |
| @NonNull |
| public T setAssociatedDisplayId(int displayId) { |
| mAssociatedDisplayId = displayId; |
| return self(); |
| } |
| |
| /** |
| * Sets the name of the virtual input device. Required. |
| * |
| * <p>The name must be unique among all input devices that belong to the same virtual |
| * device.</p> |
| * |
| * <p>The maximum allowed length of the name is 80 bytes in UTF-8 encoding, enforced by |
| * {@code UINPUT_MAX_NAME_SIZE}.</p> |
| */ |
| @NonNull |
| public T setInputDeviceName(@NonNull String deviceName) { |
| mInputDeviceName = Objects.requireNonNull(deviceName); |
| return self(); |
| } |
| |
| /** |
| * Each subclass should return itself to allow the builder to chain properly |
| */ |
| T self() { |
| return (T) this; |
| } |
| } |
| } |