1 /*
2  * Copyright (C) 2011 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.app.ActivityThread;
22 import android.os.Parcel;
23 import android.os.Parcelable;
24 import android.os.RemoteException;
25 
26 import com.android.internal.util.Preconditions;
27 
28 import java.util.Objects;
29 
30 /**
31  * A class representing a USB accessory, which is an external hardware component
32  * that communicates with an android application over USB.
33  * The accessory is the USB host and android the device side of the USB connection.
34  *
35  * <p>When the accessory connects, it reports its manufacturer and model names,
36  * the version of the accessory, and a user visible description of the accessory to the device.
37  * The manufacturer, model and version strings are used by the USB Manager to choose
38  * an appropriate application for the accessory.
39  * The accessory may optionally provide a unique serial number
40  * and a URL to for the accessory's website to the device as well.
41  *
42  * <p>An instance of this class is sent to the application via the
43  * {@link UsbManager#ACTION_USB_ACCESSORY_ATTACHED} Intent.
44  * The application can then call {@link UsbManager#openAccessory} to open a file descriptor
45  * for reading and writing data to and from the accessory.
46  *
47  * <div class="special reference">
48  * <h3>Developer Guides</h3>
49  * <p>For more information about communicating with USB hardware, read the
50  * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
51  * </div>
52  */
53 public class UsbAccessory implements Parcelable {
54 
55     private static final String TAG = "UsbAccessory";
56 
57     private final @NonNull String mManufacturer;
58     private final @NonNull String mModel;
59     private final @Nullable String mDescription;
60     private final @Nullable String mVersion;
61     private final @Nullable String mUri;
62     private final @NonNull IUsbSerialReader mSerialNumberReader;
63 
64     /** @hide */
65     public static final int MANUFACTURER_STRING = 0;
66     /** @hide */
67     public static final int MODEL_STRING = 1;
68     /** @hide */
69     public static final int DESCRIPTION_STRING = 2;
70     /** @hide */
71     public static final int VERSION_STRING = 3;
72     /** @hide */
73     public static final int URI_STRING = 4;
74     /** @hide */
75     public static final int SERIAL_STRING = 5;
76 
77     /**
78      * UsbAccessory should only be instantiated by UsbService implementation
79      * @hide
80      */
UsbAccessory(@onNull String manufacturer, @NonNull String model, @Nullable String description, @Nullable String version, @Nullable String uri, @NonNull IUsbSerialReader serialNumberReader)81     public UsbAccessory(@NonNull String manufacturer, @NonNull String model,
82             @Nullable String description, @Nullable String version, @Nullable String uri,
83             @NonNull IUsbSerialReader serialNumberReader) {
84         mManufacturer = Objects.requireNonNull(manufacturer);
85         mModel = Objects.requireNonNull(model);
86         mDescription = description;
87         mVersion = version;
88         mUri = uri;
89         mSerialNumberReader = serialNumberReader;
90 
91         // Make sure the binder belongs to the system
92         if (ActivityThread.isSystem()) {
93             Preconditions.checkArgument(mSerialNumberReader instanceof IUsbSerialReader.Stub);
94         }
95     }
96 
97     /**
98      * DO NOT USE. Only for backwards compatibility with
99      * {@link com.android.future.usb.UsbAccessory}.
100      *
101      * @hide
102      * @deprecated use {@link UsbAccessory#UsbAccessory(String, String, String, String, String,
103      *             IUsbSerialReader) instead}
104      */
105     @Deprecated
UsbAccessory(@onNull String manufacturer, @NonNull String model, @Nullable String description, @Nullable String version, @Nullable String uri, @Nullable String serialNumber)106     public UsbAccessory(@NonNull String manufacturer, @NonNull String model,
107             @Nullable String description, @Nullable String version, @Nullable String uri,
108             @Nullable String serialNumber) {
109         this(manufacturer, model, description, version, uri, new IUsbSerialReader.Stub() {
110             @Override
111             public String getSerial(String packageName) {
112                 return serialNumber;
113             }
114         });
115     }
116 
117     /**
118      * Returns the manufacturer name of the accessory.
119      *
120      * @return the accessory manufacturer
121      */
getManufacturer()122     public @NonNull String getManufacturer() {
123         return mManufacturer;
124     }
125 
126     /**
127      * Returns the model name of the accessory.
128      *
129      * @return the accessory model
130      */
getModel()131     public @NonNull String getModel() {
132         return mModel;
133     }
134 
135     /**
136      * Returns a user visible description of the accessory.
137      *
138      * @return the accessory description, or {@code null} if not set
139      */
getDescription()140     public @Nullable String getDescription() {
141         return mDescription;
142     }
143 
144     /**
145      * Returns the version of the accessory.
146      *
147      * @return the accessory version, or {@code null} if not set
148      */
getVersion()149     public @Nullable String getVersion() {
150         return mVersion;
151     }
152 
153     /**
154      * Returns the URI for the accessory.
155      * This is an optional URI that might show information about the accessory
156      * or provide the option to download an application for the accessory
157      *
158      * @return the accessory URI, or {@code null} if not set
159      */
getUri()160     public @Nullable String getUri() {
161         return mUri;
162     }
163 
164     /**
165      * Returns the unique serial number for the accessory.
166      * This is an optional serial number that can be used to differentiate
167      * between individual accessories of the same model and manufacturer
168      *
169      * @return the unique serial number, or {@code null} if not set
170      *
171      * @throws SecurityException if the app targets SDK >= {@value android.os.Build.VERSION_CODES#Q}
172      *                           and the app does not have permission to read from the accessory.
173      */
getSerial()174     public @Nullable String getSerial() {
175         try {
176             return mSerialNumberReader.getSerial(ActivityThread.currentPackageName());
177         } catch (RemoteException e) {
178             e.rethrowFromSystemServer();
179             return null;
180         }
181     }
182 
compare(String s1, String s2)183     private static boolean compare(String s1, String s2) {
184         if (s1 == null) return (s2 == null);
185         return s1.equals(s2);
186     }
187 
188     @Override
equals(@ullable Object obj)189     public boolean equals(@Nullable Object obj) {
190         if (obj instanceof UsbAccessory) {
191             UsbAccessory accessory = (UsbAccessory)obj;
192             return (compare(mManufacturer, accessory.getManufacturer()) &&
193                     compare(mModel, accessory.getModel()) &&
194                     compare(mDescription, accessory.getDescription()) &&
195                     compare(mVersion, accessory.getVersion()) &&
196                     compare(mUri, accessory.getUri()) &&
197                     compare(getSerial(), accessory.getSerial()));
198         }
199         return false;
200     }
201 
202     @Override
hashCode()203     public int hashCode() {
204         return mManufacturer.hashCode() ^ mModel.hashCode() ^
205                 (mDescription == null ? 0 : mDescription.hashCode()) ^
206                 (mVersion == null ? 0 : mVersion.hashCode()) ^
207                 (mUri == null ? 0 : mUri.hashCode());
208     }
209 
210     @Override
toString()211     public String toString() {
212         return "UsbAccessory[mManufacturer=" + mManufacturer +
213                             ", mModel=" + mModel +
214                             ", mDescription=" + mDescription +
215                             ", mVersion=" + mVersion +
216                             ", mUri=" + mUri +
217                             ", mSerialNumberReader=" + mSerialNumberReader + "]";
218     }
219 
220     public static final @android.annotation.NonNull Parcelable.Creator<UsbAccessory> CREATOR =
221         new Parcelable.Creator<UsbAccessory>() {
222         public UsbAccessory createFromParcel(Parcel in) {
223             String manufacturer = in.readString();
224             String model = in.readString();
225             String description = in.readString();
226             String version = in.readString();
227             String uri = in.readString();
228             IUsbSerialReader serialNumberReader = IUsbSerialReader.Stub.asInterface(
229                     in.readStrongBinder());
230 
231             return new UsbAccessory(manufacturer, model, description, version, uri,
232                     serialNumberReader);
233         }
234 
235         public UsbAccessory[] newArray(int size) {
236             return new UsbAccessory[size];
237         }
238     };
239 
describeContents()240     public int describeContents() {
241         return 0;
242     }
243 
writeToParcel(Parcel parcel, int flags)244     public void writeToParcel(Parcel parcel, int flags) {
245         parcel.writeString(mManufacturer);
246         parcel.writeString(mModel);
247         parcel.writeString(mDescription);
248         parcel.writeString(mVersion);
249         parcel.writeString(mUri);
250         parcel.writeStrongBinder(mSerialNumberReader.asBinder());
251    }
252 }
253