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