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