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