• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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.usb;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.UnsupportedAppUsage;
22 import android.app.ActivityThread;
23 import android.os.Parcel;
24 import android.os.Parcelable;
25 import android.os.RemoteException;
26 
27 import com.android.internal.util.Preconditions;
28 
29 /**
30  * This class represents a USB device attached to the android device with the android device
31  * acting as the USB host.
32  * Each device contains one or more {@link UsbInterface}s, each of which contains a number of
33  * {@link UsbEndpoint}s (the channels via which data is transmitted over USB).
34  *
35  * <p> This class contains information (along with {@link UsbInterface} and {@link UsbEndpoint})
36  * that describes the capabilities of the USB device.
37  * To communicate with the device, you open a {@link UsbDeviceConnection} for the device
38  * and use {@link UsbRequest} to send and receive data on an endpoint.
39  * {@link UsbDeviceConnection#controlTransfer} is used for control requests on endpoint zero.
40  *
41  * <div class="special reference">
42  * <h3>Developer Guides</h3>
43  * <p>For more information about communicating with USB hardware, read the
44  * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB</a> developer guide.</p>
45  * </div>
46  */
47 public class UsbDevice implements Parcelable {
48 
49     private static final String TAG = "UsbDevice";
50     private static final boolean DEBUG = false;
51 
52     private final @NonNull String mName;
53     private final @Nullable String mManufacturerName;
54     private final @Nullable String mProductName;
55     private final @NonNull String mVersion;
56     private final @NonNull UsbConfiguration[] mConfigurations;
57     private final @NonNull IUsbSerialReader mSerialNumberReader;
58     private final int mVendorId;
59     private final int mProductId;
60     private final int mClass;
61     private final int mSubclass;
62     private final int mProtocol;
63 
64     /** All interfaces on the device. Initialized on first call to getInterfaceList */
65     @UnsupportedAppUsage
66     private @Nullable UsbInterface[] mInterfaces;
67 
68     /**
69      * Create a new UsbDevice object. Only called by {@link Builder#build(IUsbSerialReader)}
70      *
71      * @hide
72      */
UsbDevice(@onNull String name, int vendorId, int productId, int Class, int subClass, int protocol, @Nullable String manufacturerName, @Nullable String productName, @NonNull String version, @NonNull UsbConfiguration[] configurations, @NonNull IUsbSerialReader serialNumberReader)73     private UsbDevice(@NonNull String name, int vendorId, int productId, int Class, int subClass,
74             int protocol, @Nullable String manufacturerName, @Nullable String productName,
75             @NonNull String version, @NonNull UsbConfiguration[] configurations,
76             @NonNull IUsbSerialReader serialNumberReader) {
77         mName = Preconditions.checkNotNull(name);
78         mVendorId = vendorId;
79         mProductId = productId;
80         mClass = Class;
81         mSubclass = subClass;
82         mProtocol = protocol;
83         mManufacturerName = manufacturerName;
84         mProductName = productName;
85         mVersion = Preconditions.checkStringNotEmpty(version);
86         mConfigurations = Preconditions.checkArrayElementsNotNull(configurations, "configurations");
87         mSerialNumberReader = Preconditions.checkNotNull(serialNumberReader);
88 
89         // Make sure the binder belongs to the system
90         if (ActivityThread.isSystem()) {
91             Preconditions.checkArgument(mSerialNumberReader instanceof IUsbSerialReader.Stub);
92         }
93     }
94 
95     /**
96      * Returns the name of the device.
97      * In the standard implementation, this is the path of the device file
98      * for the device in the usbfs file system.
99      *
100      * @return the device name
101      */
getDeviceName()102     public @NonNull String getDeviceName() {
103         return mName;
104     }
105 
106     /**
107      * Returns the manufacturer name of the device.
108      *
109      * @return the manufacturer name, or {@code null} if the property could not be read
110      */
getManufacturerName()111     public @Nullable String getManufacturerName() {
112         return mManufacturerName;
113     }
114 
115     /**
116      * Returns the product name of the device.
117      *
118      * @return the product name, or {@code null} if the property could not be read
119      */
getProductName()120     public @Nullable String getProductName() {
121         return mProductName;
122     }
123 
124     /**
125      * Returns the version number of the device.
126      *
127      * @return the device version
128      */
getVersion()129     public @NonNull String getVersion() {
130         return mVersion;
131     }
132 
133     /**
134      * Returns the serial number of the device.
135      *
136      * @return the serial number name, or {@code null} if the property could not be read
137      *
138      * @throws SecurityException if the app targets SDK >= {@value android.os.Build.VERSION_CODES#Q}
139      *                           and the app does not have permission to read from the device.
140      */
getSerialNumber()141     public @Nullable String getSerialNumber() {
142         try {
143             return mSerialNumberReader.getSerial(ActivityThread.currentPackageName());
144         } catch (RemoteException e) {
145             e.rethrowFromSystemServer();
146             return null;
147         }
148     }
149 
150     /**
151      * Returns a unique integer ID for the device.
152      * This is a convenience for clients that want to use an integer to represent
153      * the device, rather than the device name.
154      * IDs are not persistent across USB disconnects.
155      *
156      * @return the device ID
157      */
getDeviceId()158     public int getDeviceId() {
159         return getDeviceId(mName);
160     }
161 
162     /**
163      * Returns a vendor ID for the device.
164      *
165      * @return the device vendor ID
166      */
getVendorId()167     public int getVendorId() {
168         return mVendorId;
169     }
170 
171     /**
172      * Returns a product ID for the device.
173      *
174      * @return the device product ID
175      */
getProductId()176     public int getProductId() {
177         return mProductId;
178     }
179 
180     /**
181      * Returns the devices's class field.
182      * Some useful constants for USB device classes can be found in {@link UsbConstants}.
183      *
184      * @return the devices's class
185      */
getDeviceClass()186     public int getDeviceClass() {
187         return mClass;
188     }
189 
190     /**
191      * Returns the device's subclass field.
192      *
193      * @return the device's subclass
194      */
getDeviceSubclass()195     public int getDeviceSubclass() {
196         return mSubclass;
197     }
198 
199     /**
200      * Returns the device's protocol field.
201      *
202      * @return the device's protocol
203      */
getDeviceProtocol()204     public int getDeviceProtocol() {
205         return mProtocol;
206     }
207 
208     /**
209      * Returns the number of {@link UsbConfiguration}s this device contains.
210      *
211      * @return the number of configurations
212      */
getConfigurationCount()213     public int getConfigurationCount() {
214         return mConfigurations.length;
215     }
216 
217     /**
218      * Returns the {@link UsbConfiguration} at the given index.
219      *
220      * @return the configuration
221      */
getConfiguration(int index)222     public @NonNull UsbConfiguration getConfiguration(int index) {
223         return mConfigurations[index];
224     }
225 
getInterfaceList()226     private @Nullable UsbInterface[] getInterfaceList() {
227         if (mInterfaces == null) {
228             int configurationCount = mConfigurations.length;
229             int interfaceCount = 0;
230             for (int i = 0; i < configurationCount; i++) {
231                 UsbConfiguration configuration = mConfigurations[i];
232                 interfaceCount += configuration.getInterfaceCount();
233             }
234 
235             mInterfaces = new UsbInterface[interfaceCount];
236             int offset = 0;
237             for (int i = 0; i < configurationCount; i++) {
238                 UsbConfiguration configuration = mConfigurations[i];
239                 interfaceCount = configuration.getInterfaceCount();
240                 for (int j = 0; j < interfaceCount; j++) {
241                     mInterfaces[offset++] = configuration.getInterface(j);
242                 }
243             }
244         }
245 
246         return mInterfaces;
247     }
248 
249     /**
250      * Returns the number of {@link UsbInterface}s this device contains.
251      * For devices with multiple configurations, you will probably want to use
252      * {@link UsbConfiguration#getInterfaceCount} instead.
253      *
254      * @return the number of interfaces
255      */
getInterfaceCount()256     public int getInterfaceCount() {
257         return getInterfaceList().length;
258     }
259 
260     /**
261      * Returns the {@link UsbInterface} at the given index.
262      * For devices with multiple configurations, you will probably want to use
263      * {@link UsbConfiguration#getInterface} instead.
264      *
265      * @return the interface
266      */
getInterface(int index)267     public @NonNull UsbInterface getInterface(int index) {
268         return getInterfaceList()[index];
269     }
270 
271     @Override
equals(Object o)272     public boolean equals(Object o) {
273         if (o instanceof UsbDevice) {
274             return ((UsbDevice)o).mName.equals(mName);
275         } else if (o instanceof String) {
276             return ((String)o).equals(mName);
277         } else {
278             return false;
279         }
280     }
281 
282     @Override
hashCode()283     public int hashCode() {
284         return mName.hashCode();
285     }
286 
287     @Override
toString()288     public String toString() {
289         StringBuilder builder = new StringBuilder("UsbDevice[mName=" + mName +
290                 ",mVendorId=" + mVendorId + ",mProductId=" + mProductId +
291                 ",mClass=" + mClass + ",mSubclass=" + mSubclass + ",mProtocol=" + mProtocol +
292                 ",mManufacturerName=" + mManufacturerName + ",mProductName=" + mProductName +
293                 ",mVersion=" + mVersion + ",mSerialNumberReader=" + mSerialNumberReader
294                 + ",mConfigurations=[");
295         for (int i = 0; i < mConfigurations.length; i++) {
296             builder.append("\n");
297             builder.append(mConfigurations[i].toString());
298         }
299         builder.append("]");
300         return builder.toString();
301     }
302 
303     public static final @android.annotation.NonNull Parcelable.Creator<UsbDevice> CREATOR =
304         new Parcelable.Creator<UsbDevice>() {
305         public UsbDevice createFromParcel(Parcel in) {
306             String name = in.readString();
307             int vendorId = in.readInt();
308             int productId = in.readInt();
309             int clasz = in.readInt();
310             int subClass = in.readInt();
311             int protocol = in.readInt();
312             String manufacturerName = in.readString();
313             String productName = in.readString();
314             String version = in.readString();
315             IUsbSerialReader serialNumberReader =
316                     IUsbSerialReader.Stub.asInterface(in.readStrongBinder());
317             UsbConfiguration[] configurations = in.readParcelableArray(
318                     UsbConfiguration.class.getClassLoader(), UsbConfiguration.class);
319             UsbDevice device = new UsbDevice(name, vendorId, productId, clasz, subClass, protocol,
320                                  manufacturerName, productName, version, configurations,
321                     serialNumberReader);
322             return device;
323         }
324 
325         public UsbDevice[] newArray(int size) {
326             return new UsbDevice[size];
327         }
328     };
329 
describeContents()330     public int describeContents() {
331         return 0;
332     }
333 
writeToParcel(Parcel parcel, int flags)334     public void writeToParcel(Parcel parcel, int flags) {
335         parcel.writeString(mName);
336         parcel.writeInt(mVendorId);
337         parcel.writeInt(mProductId);
338         parcel.writeInt(mClass);
339         parcel.writeInt(mSubclass);
340         parcel.writeInt(mProtocol);
341         parcel.writeString(mManufacturerName);
342         parcel.writeString(mProductName);
343         parcel.writeString(mVersion);
344         parcel.writeStrongBinder(mSerialNumberReader.asBinder());
345         parcel.writeParcelableArray(mConfigurations, 0);
346    }
347 
getDeviceId(String name)348     public static int getDeviceId(String name) {
349         return native_get_device_id(name);
350     }
351 
getDeviceName(int id)352     public static String getDeviceName(int id) {
353         return native_get_device_name(id);
354     }
355 
native_get_device_id(String name)356     private static native int native_get_device_id(String name);
native_get_device_name(int id)357     private static native String native_get_device_name(int id);
358 
359     /**
360      * @hide
361      */
362     public static class Builder {
363         private final @NonNull String mName;
364         private final int mVendorId;
365         private final int mProductId;
366         private final int mClass;
367         private final int mSubclass;
368         private final int mProtocol;
369         private final @Nullable String mManufacturerName;
370         private final @Nullable String mProductName;
371         private final @NonNull String mVersion;
372         private final @NonNull UsbConfiguration[] mConfigurations;
373 
374         // Temporary storage for serial number. Serial number reader need to be wrapped in a
375         // IUsbSerialReader as they might be used as PII.
376         public final @Nullable String serialNumber;
377 
Builder(@onNull String name, int vendorId, int productId, int Class, int subClass, int protocol, @Nullable String manufacturerName, @Nullable String productName, @NonNull String version, @NonNull UsbConfiguration[] configurations, @Nullable String serialNumber)378         public Builder(@NonNull String name, int vendorId, int productId, int Class, int subClass,
379                 int protocol, @Nullable String manufacturerName, @Nullable String productName,
380                 @NonNull String version, @NonNull UsbConfiguration[] configurations,
381                 @Nullable String serialNumber) {
382             mName = Preconditions.checkNotNull(name);
383             mVendorId = vendorId;
384             mProductId = productId;
385             mClass = Class;
386             mSubclass = subClass;
387             mProtocol = protocol;
388             mManufacturerName = manufacturerName;
389             mProductName = productName;
390             mVersion = Preconditions.checkStringNotEmpty(version);
391             mConfigurations = configurations;
392             this.serialNumber = serialNumber;
393         }
394 
395         /**
396          * Create a new {@link UsbDevice}
397          *
398          * @param serialReader The method to read the serial number.
399          *
400          * @return The usb device
401          */
build(@onNull IUsbSerialReader serialReader)402         public UsbDevice build(@NonNull IUsbSerialReader serialReader) {
403             return new UsbDevice(mName, mVendorId, mProductId, mClass, mSubclass, mProtocol,
404                     mManufacturerName, mProductName, mVersion, mConfigurations, serialReader);
405         }
406     }
407 }
408