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