UsbManager.java revision f59717ddb5ef324ee3fdb12b83e7d1b709793d28
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 */
41public 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     * Sets the current USB function.
412     *
413     * @param function name of the USB function
414     * @param makeDefault true if this should be set as the default
415     *
416     * {@hide}
417     */
418    public void setCurrentFunction(String function, boolean makeDefault) {
419        try {
420            mService.setCurrentFunction(function, makeDefault);
421        } catch (RemoteException e) {
422            Log.e(TAG, "RemoteException in setCurrentFunction", e);
423        }
424    }
425
426    /**
427     * Sets the file path for USB mass storage backing file.
428     *
429     * @param path backing file path
430     *
431     * {@hide}
432     */
433    public void setMassStorageBackingFile(String path) {
434        try {
435            mService.setMassStorageBackingFile(path);
436        } catch (RemoteException e) {
437            Log.e(TAG, "RemoteException in setDefaultFunction", e);
438        }
439    }
440}
441