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