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