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