• 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 
18 package android.hardware.usb;
19 
20 import android.app.PendingIntent;
21 import android.content.Context;
22 import android.os.Bundle;
23 import android.os.ParcelFileDescriptor;
24 import android.os.RemoteException;
25 import android.os.SystemProperties;
26 import android.util.Log;
27 
28 import java.util.HashMap;
29 
30 /**
31  * This class allows you to access the state of USB and communicate with USB devices.
32  * Currently only host mode is supported in the public API.
33  *
34  * <p>You can obtain an instance of this class by calling
35  * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
36  *
37  * {@samplecode
38  * UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);}
39  *
40  * <div class="special reference">
41  * <h3>Developer Guides</h3>
42  * <p>For more information about communicating with USB hardware, read the
43  * <a href="{@docRoot}guide/topics/usb/index.html">USB</a> developer guide.</p>
44  * </div>
45  */
46 public class UsbManager {
47     private static final String TAG = "UsbManager";
48 
49    /**
50      * Broadcast Action:  A sticky broadcast for USB state change events when in device mode.
51      *
52      * This is a sticky broadcast for clients that includes USB connected/disconnected state,
53      * <ul>
54      * <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
55      * <li> {@link #USB_CONFIGURED} boolean indicating whether USB is configured.
56      * currently zero if not configured, one for configured.
57      * <li> {@link #USB_FUNCTION_MASS_STORAGE} boolean extra indicating whether the
58      * mass storage function is enabled
59      * <li> {@link #USB_FUNCTION_ADB} boolean extra indicating whether the
60      * adb function is enabled
61      * <li> {@link #USB_FUNCTION_RNDIS} boolean extra indicating whether the
62      * RNDIS ethernet function is enabled
63      * <li> {@link #USB_FUNCTION_MTP} boolean extra indicating whether the
64      * MTP function is enabled
65      * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
66      * PTP function is enabled
67      * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
68      * accessory function is enabled
69      * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
70      * audio source function is enabled
71      * </ul>
72      *
73      * {@hide}
74      */
75     public static final String ACTION_USB_STATE =
76             "android.hardware.usb.action.USB_STATE";
77 
78    /**
79      * Broadcast Action:  A broadcast for USB device attached event.
80      *
81      * This intent is sent when a USB device is attached to the USB bus when in host mode.
82      * <ul>
83      * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice}
84      * for the attached device
85      * </ul>
86      */
87     public static final String ACTION_USB_DEVICE_ATTACHED =
88             "android.hardware.usb.action.USB_DEVICE_ATTACHED";
89 
90    /**
91      * Broadcast Action:  A broadcast for USB device detached event.
92      *
93      * This intent is sent when a USB device is detached from the USB bus when in host mode.
94      * <ul>
95      * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice}
96      * for the detached device
97      * </ul>
98      */
99     public static final String ACTION_USB_DEVICE_DETACHED =
100             "android.hardware.usb.action.USB_DEVICE_DETACHED";
101 
102    /**
103      * Broadcast Action:  A broadcast for USB accessory attached event.
104      *
105      * This intent is sent when a USB accessory is attached.
106      * <ul>
107      * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.usb.UsbAccessory}
108      * for the attached accessory
109      * </ul>
110      */
111     public static final String ACTION_USB_ACCESSORY_ATTACHED =
112             "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
113 
114    /**
115      * Broadcast Action:  A broadcast for USB accessory detached event.
116      *
117      * This intent is sent when a USB accessory is detached.
118      * <ul>
119      * <li> {@link #EXTRA_ACCESSORY} containing the {@link UsbAccessory}
120      * for the attached accessory that was detached
121      * </ul>
122      */
123     public static final String ACTION_USB_ACCESSORY_DETACHED =
124             "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
125 
126     /**
127      * Boolean extra indicating whether USB is connected or disconnected.
128      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
129      *
130      * {@hide}
131      */
132     public static final String USB_CONNECTED = "connected";
133 
134     /**
135      * Boolean extra indicating whether USB is configured.
136      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
137      *
138      * {@hide}
139      */
140     public static final String USB_CONFIGURED = "configured";
141 
142     /**
143      * Name of the USB mass storage USB function.
144      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
145      *
146      * {@hide}
147      */
148     public static final String USB_FUNCTION_MASS_STORAGE = "mass_storage";
149 
150     /**
151      * Name of the adb USB function.
152      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
153      *
154      * {@hide}
155      */
156     public static final String USB_FUNCTION_ADB = "adb";
157 
158     /**
159      * Name of the RNDIS ethernet USB function.
160      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
161      *
162      * {@hide}
163      */
164     public static final String USB_FUNCTION_RNDIS = "rndis";
165 
166     /**
167      * Name of the MTP USB function.
168      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
169      *
170      * {@hide}
171      */
172     public static final String USB_FUNCTION_MTP = "mtp";
173 
174     /**
175      * Name of the PTP USB function.
176      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
177      *
178      * {@hide}
179      */
180     public static final String USB_FUNCTION_PTP = "ptp";
181 
182     /**
183      * Name of the audio source USB function.
184      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
185      *
186      * {@hide}
187      */
188     public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";
189 
190     /**
191      * Name of the Accessory USB function.
192      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
193      *
194      * {@hide}
195      */
196     public static final String USB_FUNCTION_ACCESSORY = "accessory";
197 
198     /**
199      * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and
200      * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts
201      * containing the UsbDevice object for the device.
202      */
203 
204     public static final String EXTRA_DEVICE = "device";
205 
206     /**
207      * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} and
208      * {@link #ACTION_USB_ACCESSORY_DETACHED} broadcasts
209      * containing the UsbAccessory object for the accessory.
210      */
211     public static final String EXTRA_ACCESSORY = "accessory";
212 
213     /**
214      * Name of extra added to the {@link android.app.PendingIntent}
215      * passed into {@link #requestPermission(UsbDevice, PendingIntent)}
216      * or {@link #requestPermission(UsbAccessory, PendingIntent)}
217      * containing a boolean value indicating whether the user granted permission or not.
218      */
219     public static final String EXTRA_PERMISSION_GRANTED = "permission";
220 
221     private final Context mContext;
222     private final IUsbManager mService;
223 
224     /**
225      * {@hide}
226      */
UsbManager(Context context, IUsbManager service)227     public UsbManager(Context context, IUsbManager service) {
228         mContext = context;
229         mService = service;
230     }
231 
232     /**
233      * Returns a HashMap containing all USB devices currently attached.
234      * USB device name is the key for the returned HashMap.
235      * The result will be empty if no devices are attached, or if
236      * USB host mode is inactive or unsupported.
237      *
238      * @return HashMap containing all connected USB devices.
239      */
getDeviceList()240     public HashMap<String,UsbDevice> getDeviceList() {
241         Bundle bundle = new Bundle();
242         try {
243             mService.getDeviceList(bundle);
244             HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>();
245             for (String name : bundle.keySet()) {
246                 result.put(name, (UsbDevice)bundle.get(name));
247             }
248             return result;
249         } catch (RemoteException e) {
250             Log.e(TAG, "RemoteException in getDeviceList", e);
251             return null;
252         }
253     }
254 
255     /**
256      * Opens the device so it can be used to send and receive
257      * data using {@link android.hardware.usb.UsbRequest}.
258      *
259      * @param device the device to open
260      * @return true if we successfully opened the device
261      */
openDevice(UsbDevice device)262     public UsbDeviceConnection openDevice(UsbDevice device) {
263         try {
264             String deviceName = device.getDeviceName();
265             ParcelFileDescriptor pfd = mService.openDevice(deviceName);
266             if (pfd != null) {
267                 UsbDeviceConnection connection = new UsbDeviceConnection(device);
268                 boolean result = connection.open(deviceName, pfd);
269                 pfd.close();
270                 if (result) {
271                     return connection;
272                 }
273             }
274         } catch (Exception e) {
275             Log.e(TAG, "exception in UsbManager.openDevice", e);
276         }
277         return null;
278     }
279 
280     /**
281      * Returns a list of currently attached USB accessories.
282      * (in the current implementation there can be at most one)
283      *
284      * @return list of USB accessories, or null if none are attached.
285      */
getAccessoryList()286     public UsbAccessory[] getAccessoryList() {
287         try {
288             UsbAccessory accessory = mService.getCurrentAccessory();
289             if (accessory == null) {
290                 return null;
291             } else {
292                 return new UsbAccessory[] { accessory };
293             }
294         } catch (RemoteException e) {
295             Log.e(TAG, "RemoteException in getAccessoryList", e);
296             return null;
297         }
298     }
299 
300     /**
301      * Opens a file descriptor for reading and writing data to the USB accessory.
302      *
303      * @param accessory the USB accessory to open
304      * @return file descriptor, or null if the accessor could not be opened.
305      */
openAccessory(UsbAccessory accessory)306     public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
307         try {
308             return mService.openAccessory(accessory);
309         } catch (RemoteException e) {
310             Log.e(TAG, "RemoteException in openAccessory", e);
311             return null;
312         }
313     }
314 
315     /**
316      * Returns true if the caller has permission to access the device.
317      * Permission might have been granted temporarily via
318      * {@link #requestPermission(UsbDevice, PendingIntent)} or
319      * by the user choosing the caller as the default application for the device.
320      *
321      * @param device to check permissions for
322      * @return true if caller has permission
323      */
hasPermission(UsbDevice device)324     public boolean hasPermission(UsbDevice device) {
325         try {
326             return mService.hasDevicePermission(device);
327         } catch (RemoteException e) {
328             Log.e(TAG, "RemoteException in hasPermission", e);
329             return false;
330         }
331     }
332 
333     /**
334      * Returns true if the caller has permission to access the accessory.
335      * Permission might have been granted temporarily via
336      * {@link #requestPermission(UsbAccessory, PendingIntent)} or
337      * by the user choosing the caller as the default application for the accessory.
338      *
339      * @param accessory to check permissions for
340      * @return true if caller has permission
341      */
hasPermission(UsbAccessory accessory)342     public boolean hasPermission(UsbAccessory accessory) {
343         try {
344             return mService.hasAccessoryPermission(accessory);
345         } catch (RemoteException e) {
346             Log.e(TAG, "RemoteException in hasPermission", e);
347             return false;
348         }
349     }
350 
351     /**
352      * Requests temporary permission for the given package to access the device.
353      * This may result in a system dialog being displayed to the user
354      * if permission had not already been granted.
355      * Success or failure is returned via the {@link android.app.PendingIntent} pi.
356      * If successful, this grants the caller permission to access the device only
357      * until the device is disconnected.
358      *
359      * The following extras will be added to pi:
360      * <ul>
361      * <li> {@link #EXTRA_DEVICE} containing the device passed into this call
362      * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether
363      * permission was granted by the user
364      * </ul>
365      *
366      * @param device to request permissions for
367      * @param pi PendingIntent for returning result
368      */
requestPermission(UsbDevice device, PendingIntent pi)369     public void requestPermission(UsbDevice device, PendingIntent pi) {
370         try {
371             mService.requestDevicePermission(device, mContext.getPackageName(), pi);
372         } catch (RemoteException e) {
373             Log.e(TAG, "RemoteException in requestPermission", e);
374         }
375     }
376 
377     /**
378      * Requests temporary permission for the given package to access the accessory.
379      * This may result in a system dialog being displayed to the user
380      * if permission had not already been granted.
381      * Success or failure is returned via the {@link android.app.PendingIntent} pi.
382      * If successful, this grants the caller permission to access the accessory only
383      * until the device is disconnected.
384      *
385      * The following extras will be added to pi:
386      * <ul>
387      * <li> {@link #EXTRA_ACCESSORY} containing the accessory passed into this call
388      * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether
389      * permission was granted by the user
390      * </ul>
391      *
392      * @param accessory to request permissions for
393      * @param pi PendingIntent for returning result
394      */
requestPermission(UsbAccessory accessory, PendingIntent pi)395     public void requestPermission(UsbAccessory accessory, PendingIntent pi) {
396         try {
397             mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi);
398         } catch (RemoteException e) {
399             Log.e(TAG, "RemoteException in requestPermission", e);
400         }
401     }
402 
propertyContainsFunction(String property, String function)403     private static boolean propertyContainsFunction(String property, String function) {
404         String functions = SystemProperties.get(property, "");
405         int index = functions.indexOf(function);
406         if (index < 0) return false;
407         if (index > 0 && functions.charAt(index - 1) != ',') return false;
408         int charAfter = index + function.length();
409         if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
410         return true;
411     }
412 
413     /**
414      * Returns true if the specified USB function is currently enabled.
415      *
416      * @param function name of the USB function
417      * @return true if the USB function is enabled.
418      *
419      * {@hide}
420      */
isFunctionEnabled(String function)421     public boolean isFunctionEnabled(String function) {
422         return propertyContainsFunction("sys.usb.config", function);
423     }
424 
425     /**
426      * Returns the current default USB function.
427      *
428      * @return name of the default function.
429      *
430      * {@hide}
431      */
getDefaultFunction()432     public String getDefaultFunction() {
433         String functions = SystemProperties.get("persist.sys.usb.config", "");
434         int commaIndex = functions.indexOf(',');
435         if (commaIndex > 0) {
436             return functions.substring(0, commaIndex);
437         } else {
438             return functions;
439         }
440     }
441 
442     /**
443      * Sets the current USB function.
444      * If function is null, then the current function is set to the default function.
445      *
446      * @param function name of the USB function, or null to restore the default function
447      * @param makeDefault true if the function should be set as the new default function
448      *
449      * {@hide}
450      */
setCurrentFunction(String function, boolean makeDefault)451     public void setCurrentFunction(String function, boolean makeDefault) {
452         try {
453             mService.setCurrentFunction(function, makeDefault);
454         } catch (RemoteException e) {
455             Log.e(TAG, "RemoteException in setCurrentFunction", e);
456         }
457     }
458 
459     /**
460      * Sets the file path for USB mass storage backing file.
461      *
462      * @param path backing file path
463      *
464      * {@hide}
465      */
setMassStorageBackingFile(String path)466     public void setMassStorageBackingFile(String path) {
467         try {
468             mService.setMassStorageBackingFile(path);
469         } catch (RemoteException e) {
470             Log.e(TAG, "RemoteException in setDefaultFunction", e);
471         }
472     }
473 }
474