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