1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.hardware.input; 18 19 import android.annotation.NonNull; 20 import android.annotation.SystemApi; 21 import android.os.Parcel; 22 import android.view.Display; 23 24 import java.nio.charset.StandardCharsets; 25 import java.util.Objects; 26 27 /** 28 * Common configurations to create virtual input devices. 29 * 30 * @hide 31 */ 32 @SystemApi 33 public abstract class VirtualInputDeviceConfig { 34 35 /** 36 * The maximum length of a device name (in bytes in UTF-8 encoding). 37 * 38 * This limitation comes directly from uinput. 39 * See also UINPUT_MAX_NAME_SIZE in linux/uinput.h 40 */ 41 private static final int DEVICE_NAME_MAX_LENGTH = 80; 42 43 /** The vendor id uniquely identifies the company who manufactured the device. */ 44 private final int mVendorId; 45 /** 46 * The product id uniquely identifies which product within the address space of a given vendor, 47 * identified by the device's vendor id. 48 */ 49 private final int mProductId; 50 /** The associated display ID of the virtual input device. */ 51 private final int mAssociatedDisplayId; 52 /** The name of the virtual input device. */ 53 @NonNull 54 private final String mInputDeviceName; 55 VirtualInputDeviceConfig(@onNull Builder<? extends Builder<?>> builder)56 protected VirtualInputDeviceConfig(@NonNull Builder<? extends Builder<?>> builder) { 57 mVendorId = builder.mVendorId; 58 mProductId = builder.mProductId; 59 mAssociatedDisplayId = builder.mAssociatedDisplayId; 60 mInputDeviceName = Objects.requireNonNull(builder.mInputDeviceName); 61 62 if (mAssociatedDisplayId == Display.INVALID_DISPLAY) { 63 throw new IllegalArgumentException( 64 "Display association is required for virtual input devices."); 65 } 66 67 // Comparison is greater or equal because the device name must fit into a const char* 68 // including the \0-terminator. Therefore the actual number of bytes that can be used 69 // for device name is DEVICE_NAME_MAX_LENGTH - 1 70 if (mInputDeviceName.getBytes(StandardCharsets.UTF_8).length >= DEVICE_NAME_MAX_LENGTH) { 71 throw new IllegalArgumentException("Input device name exceeds maximum length of " 72 + DEVICE_NAME_MAX_LENGTH + "bytes: " + mInputDeviceName); 73 } 74 } 75 VirtualInputDeviceConfig(@onNull Parcel in)76 protected VirtualInputDeviceConfig(@NonNull Parcel in) { 77 mVendorId = in.readInt(); 78 mProductId = in.readInt(); 79 mAssociatedDisplayId = in.readInt(); 80 mInputDeviceName = Objects.requireNonNull(in.readString8()); 81 } 82 83 /** 84 * The vendor id uniquely identifies the company who manufactured the device. 85 * 86 * @see Builder#setVendorId(int) (int) 87 */ getVendorId()88 public int getVendorId() { 89 return mVendorId; 90 } 91 92 /** 93 * The product id uniquely identifies which product within the address space of a given vendor, 94 * identified by the device's vendor id. 95 * 96 * @see Builder#setProductId(int) 97 */ getProductId()98 public int getProductId() { 99 return mProductId; 100 } 101 102 /** 103 * The associated display ID of the virtual input device. 104 * 105 * @see Builder#setAssociatedDisplayId(int) 106 */ getAssociatedDisplayId()107 public int getAssociatedDisplayId() { 108 return mAssociatedDisplayId; 109 } 110 111 /** 112 * The name of the virtual input device. 113 * 114 * @see Builder#setInputDeviceName(String) 115 */ 116 @NonNull getInputDeviceName()117 public String getInputDeviceName() { 118 return mInputDeviceName; 119 } 120 writeToParcel(@onNull Parcel dest, int flags)121 void writeToParcel(@NonNull Parcel dest, int flags) { 122 dest.writeInt(mVendorId); 123 dest.writeInt(mProductId); 124 dest.writeInt(mAssociatedDisplayId); 125 dest.writeString8(mInputDeviceName); 126 } 127 128 @Override toString()129 public String toString() { 130 return getClass().getName() + "( " 131 + " name=" + mInputDeviceName 132 + " vendorId=" + mVendorId 133 + " productId=" + mProductId 134 + " associatedDisplayId=" + mAssociatedDisplayId 135 + additionalFieldsToString() + ")"; 136 } 137 138 /** @hide */ 139 @NonNull additionalFieldsToString()140 String additionalFieldsToString() { 141 return ""; 142 } 143 144 /** 145 * A builder for {@link VirtualInputDeviceConfig} 146 * 147 * @param <T> The subclass to be built. 148 */ 149 @SuppressWarnings({"StaticFinalBuilder", "MissingBuildMethod"}) 150 public abstract static class Builder<T extends Builder<T>> { 151 152 private int mVendorId; 153 private int mProductId; 154 private int mAssociatedDisplayId = Display.INVALID_DISPLAY; 155 private String mInputDeviceName; 156 157 /** 158 * Sets the vendor id of the device, identifying the company who manufactured the device. 159 */ 160 @NonNull setVendorId(int vendorId)161 public T setVendorId(int vendorId) { 162 mVendorId = vendorId; 163 return self(); 164 } 165 166 167 /** 168 * Sets the product id of the device, uniquely identifying the device within the address 169 * space of a given vendor, identified by the device's vendor id. 170 */ 171 @NonNull setProductId(int productId)172 public T setProductId(int productId) { 173 mProductId = productId; 174 return self(); 175 } 176 177 /** 178 * Sets the associated display ID of the virtual input device. Required. 179 * 180 * <p>The input device is restricted to the display with the given ID and may not send 181 * events to any other display.</p> 182 */ 183 @NonNull setAssociatedDisplayId(int displayId)184 public T setAssociatedDisplayId(int displayId) { 185 mAssociatedDisplayId = displayId; 186 return self(); 187 } 188 189 /** 190 * Sets the name of the virtual input device. Required. 191 * 192 * <p>The name must be unique among all input devices that belong to the same virtual 193 * device.</p> 194 * 195 * <p>The maximum allowed length of the name is 80 bytes in UTF-8 encoding, enforced by 196 * {@code UINPUT_MAX_NAME_SIZE}.</p> 197 */ 198 @NonNull setInputDeviceName(@onNull String deviceName)199 public T setInputDeviceName(@NonNull String deviceName) { 200 mInputDeviceName = Objects.requireNonNull(deviceName); 201 return self(); 202 } 203 204 /** 205 * Each subclass should return itself to allow the builder to chain properly 206 */ self()207 T self() { 208 return (T) this; 209 } 210 } 211 } 212