• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.Manifest;
21 import android.annotation.NonNull;
22 import android.annotation.Nullable;
23 import android.annotation.RequiresFeature;
24 import android.annotation.RequiresPermission;
25 import android.annotation.SdkConstant;
26 import android.annotation.SdkConstant.SdkConstantType;
27 import android.annotation.SystemApi;
28 import android.annotation.SystemService;
29 import android.annotation.UnsupportedAppUsage;
30 import android.app.PendingIntent;
31 import android.content.ComponentName;
32 import android.content.Context;
33 import android.content.pm.PackageManager;
34 import android.content.pm.PackageManager.NameNotFoundException;
35 import android.hardware.usb.gadget.V1_0.GadgetFunction;
36 import android.os.Build;
37 import android.os.Bundle;
38 import android.os.ParcelFileDescriptor;
39 import android.os.Process;
40 import android.os.RemoteException;
41 import android.util.Log;
42 
43 import java.util.ArrayList;
44 import java.util.Collections;
45 import java.util.HashMap;
46 import java.util.List;
47 import java.util.Map;
48 import java.util.StringJoiner;
49 
50 /**
51  * This class allows you to access the state of USB and communicate with USB devices.
52  * Currently only host mode is supported in the public API.
53  *
54  * <div class="special reference">
55  * <h3>Developer Guides</h3>
56  * <p>For more information about communicating with USB hardware, read the
57  * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p>
58  * </div>
59  */
60 @SystemService(Context.USB_SERVICE)
61 public class UsbManager {
62     private static final String TAG = "UsbManager";
63 
64    /**
65      * Broadcast Action:  A sticky broadcast for USB state change events when in device mode.
66      *
67      * This is a sticky broadcast for clients that includes USB connected/disconnected state,
68      * <ul>
69      * <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
70      * <li> {@link #USB_HOST_CONNECTED} boolean indicating whether USB is connected or
71      *     disconnected as host.
72      * <li> {@link #USB_CONFIGURED} boolean indicating whether USB is configured.
73      * currently zero if not configured, one for configured.
74      * <li> {@link #USB_FUNCTION_ADB} boolean extra indicating whether the
75      * adb function is enabled
76      * <li> {@link #USB_FUNCTION_RNDIS} boolean extra indicating whether the
77      * RNDIS ethernet function is enabled
78      * <li> {@link #USB_FUNCTION_MTP} boolean extra indicating whether the
79      * MTP function is enabled
80      * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the
81      * PTP function is enabled
82      * <li> {@link #USB_FUNCTION_ACCESSORY} boolean extra indicating whether the
83      * accessory function is enabled
84      * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the
85      * audio source function is enabled
86      * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the
87      * MIDI function is enabled
88      * </ul>
89      * If the sticky intent has not been found, that indicates USB is disconnected,
90      * USB is not configued, MTP function is enabled, and all the other functions are disabled.
91      *
92      * {@hide}
93      */
94     @UnsupportedAppUsage
95     public static final String ACTION_USB_STATE =
96             "android.hardware.usb.action.USB_STATE";
97 
98     /**
99      * Broadcast Action: A broadcast for USB port changes.
100      *
101      * This intent is sent when a USB port is added, removed, or changes state.
102      *
103      * @hide
104      */
105     @SystemApi
106     @RequiresPermission(Manifest.permission.MANAGE_USB)
107     public static final String ACTION_USB_PORT_CHANGED =
108             "android.hardware.usb.action.USB_PORT_CHANGED";
109 
110    /**
111      * Activity intent sent when user attaches a USB device.
112      *
113      * This intent is sent when a USB device is attached to the USB bus when in host mode.
114      * <ul>
115      * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice}
116      * for the attached device
117      * </ul>
118      */
119     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
120     public static final String ACTION_USB_DEVICE_ATTACHED =
121             "android.hardware.usb.action.USB_DEVICE_ATTACHED";
122 
123    /**
124      * Broadcast Action:  A broadcast for USB device detached event.
125      *
126      * This intent is sent when a USB device is detached from the USB bus when in host mode.
127      * <ul>
128      * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice}
129      * for the detached device
130      * </ul>
131      */
132     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
133     public static final String ACTION_USB_DEVICE_DETACHED =
134             "android.hardware.usb.action.USB_DEVICE_DETACHED";
135 
136    /**
137      * Activity intent sent when user attaches a USB accessory.
138      *
139      * <ul>
140      * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.usb.UsbAccessory}
141      * for the attached accessory
142      * </ul>
143      */
144     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
145     public static final String ACTION_USB_ACCESSORY_ATTACHED =
146             "android.hardware.usb.action.USB_ACCESSORY_ATTACHED";
147 
148    /**
149      * Broadcast Action:  A broadcast for USB accessory detached event.
150      *
151      * This intent is sent when a USB accessory is detached.
152      * <ul>
153      * <li> {@link #EXTRA_ACCESSORY} containing the {@link UsbAccessory}
154      * for the attached accessory that was detached
155      * </ul>
156      */
157     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
158     public static final String ACTION_USB_ACCESSORY_DETACHED =
159             "android.hardware.usb.action.USB_ACCESSORY_DETACHED";
160 
161     /**
162      * Boolean extra indicating whether USB is connected or disconnected.
163      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
164      *
165      * {@hide}
166      */
167     @UnsupportedAppUsage
168     public static final String USB_CONNECTED = "connected";
169 
170     /**
171      * Boolean extra indicating whether USB is connected or disconnected as host.
172      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
173      *
174      * {@hide}
175      */
176     public static final String USB_HOST_CONNECTED = "host_connected";
177 
178     /**
179      * Boolean extra indicating whether USB is configured.
180      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
181      *
182      * {@hide}
183      */
184     public static final String USB_CONFIGURED = "configured";
185 
186     /**
187      * Boolean extra indicating whether confidential user data, such as photos, should be
188      * made available on the USB connection. This variable will only be set when the user
189      * has explicitly asked for this data to be unlocked.
190      * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
191      *
192      * {@hide}
193      */
194     @UnsupportedAppUsage
195     public static final String USB_DATA_UNLOCKED = "unlocked";
196 
197     /**
198      * A placeholder indicating that no USB function is being specified.
199      * Used for compatibility with old init scripts to indicate no functions vs. charging function.
200      *
201      * {@hide}
202      */
203     @UnsupportedAppUsage
204     public static final String USB_FUNCTION_NONE = "none";
205 
206     /**
207      * Name of the adb USB function.
208      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
209      *
210      * {@hide}
211      */
212     public static final String USB_FUNCTION_ADB = "adb";
213 
214     /**
215      * Name of the RNDIS ethernet USB function.
216      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
217      *
218      * {@hide}
219      */
220     public static final String USB_FUNCTION_RNDIS = "rndis";
221 
222     /**
223      * Name of the MTP USB function.
224      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
225      *
226      * {@hide}
227      */
228     public static final String USB_FUNCTION_MTP = "mtp";
229 
230     /**
231      * Name of the PTP USB function.
232      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
233      *
234      * {@hide}
235      */
236     public static final String USB_FUNCTION_PTP = "ptp";
237 
238     /**
239      * Name of the audio source USB function.
240      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
241      *
242      * {@hide}
243      */
244     public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source";
245 
246     /**
247      * Name of the MIDI USB function.
248      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
249      *
250      * {@hide}
251      */
252     public static final String USB_FUNCTION_MIDI = "midi";
253 
254     /**
255      * Name of the Accessory USB function.
256      * Used in extras for the {@link #ACTION_USB_STATE} broadcast
257      *
258      * {@hide}
259      */
260     public static final String USB_FUNCTION_ACCESSORY = "accessory";
261 
262     /**
263      * Name of extra for {@link #ACTION_USB_PORT_CHANGED}
264      * containing the {@link UsbPort} object for the port.
265      *
266      * @hide
267      */
268     public static final String EXTRA_PORT = "port";
269 
270     /**
271      * Name of extra for {@link #ACTION_USB_PORT_CHANGED}
272      * containing the {@link UsbPortStatus} object for the port, or null if the port
273      * was removed.
274      *
275      * @hide
276      */
277     public static final String EXTRA_PORT_STATUS = "portStatus";
278 
279     /**
280      * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and
281      * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts
282      * containing the {@link UsbDevice} object for the device.
283      */
284     public static final String EXTRA_DEVICE = "device";
285 
286     /**
287      * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} and
288      * {@link #ACTION_USB_ACCESSORY_DETACHED} broadcasts
289      * containing the {@link UsbAccessory} object for the accessory.
290      */
291     public static final String EXTRA_ACCESSORY = "accessory";
292 
293     /**
294      * Name of extra added to the {@link android.app.PendingIntent}
295      * passed into {@link #requestPermission(UsbDevice, PendingIntent)}
296      * or {@link #requestPermission(UsbAccessory, PendingIntent)}
297      * containing a boolean value indicating whether the user granted permission or not.
298      */
299     public static final String EXTRA_PERMISSION_GRANTED = "permission";
300 
301     /**
302      * Name of extra added to start systemui.usb.UsbPermissionActivity
303      * containing package name of the app which requests USB permission.
304      *
305      * @hide
306      */
307     public static final String EXTRA_PACKAGE = "android.hardware.usb.extra.PACKAGE";
308 
309     /**
310      * Name of extra added to start systemui.usb.UsbPermissionActivity
311      * containing the whether the app which requests USB permission can be set as default handler
312      * for USB device attach event or USB accessory attach event or not.
313      *
314      * @hide
315      */
316     public static final String EXTRA_CAN_BE_DEFAULT = "android.hardware.usb.extra.CAN_BE_DEFAULT";
317 
318     /**
319      * Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)}
320      * {@hide}
321      */
322     public static final long FUNCTION_NONE = 0;
323 
324     /**
325      * Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
326      * {@hide}
327      */
328     public static final long FUNCTION_MTP = GadgetFunction.MTP;
329 
330     /**
331      * Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
332      * {@hide}
333      */
334     public static final long FUNCTION_PTP = GadgetFunction.PTP;
335 
336     /**
337      * Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
338      * {@hide}
339      */
340     public static final long FUNCTION_RNDIS = GadgetFunction.RNDIS;
341 
342     /**
343      * Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
344      * {@hide}
345      */
346     public static final long FUNCTION_MIDI = GadgetFunction.MIDI;
347 
348     /**
349      * Code for the accessory usb function.
350      * {@hide}
351      */
352     public static final long FUNCTION_ACCESSORY = GadgetFunction.ACCESSORY;
353 
354     /**
355      * Code for the audio source usb function.
356      * {@hide}
357      */
358     public static final long FUNCTION_AUDIO_SOURCE = GadgetFunction.AUDIO_SOURCE;
359 
360     /**
361      * Code for the adb usb function.
362      * {@hide}
363      */
364     public static final long FUNCTION_ADB = GadgetFunction.ADB;
365 
366     private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS
367             | FUNCTION_MIDI;
368 
369     private static final Map<String, Long> FUNCTION_NAME_TO_CODE = new HashMap<>();
370 
371     static {
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MTP, FUNCTION_MTP)372         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MTP, FUNCTION_MTP);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_PTP, FUNCTION_PTP)373         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_PTP, FUNCTION_PTP);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_RNDIS, FUNCTION_RNDIS)374         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_RNDIS, FUNCTION_RNDIS);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MIDI, FUNCTION_MIDI)375         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MIDI, FUNCTION_MIDI);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY)376         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE)377         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE);
FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB)378         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB);
379     }
380 
381     private final Context mContext;
382     private final IUsbManager mService;
383 
384     /**
385      * {@hide}
386      */
387     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
UsbManager(Context context, IUsbManager service)388     public UsbManager(Context context, IUsbManager service) {
389         mContext = context;
390         mService = service;
391     }
392 
393     /**
394      * Returns a HashMap containing all USB devices currently attached.
395      * USB device name is the key for the returned HashMap.
396      * The result will be empty if no devices are attached, or if
397      * USB host mode is inactive or unsupported.
398      *
399      * @return HashMap containing all connected USB devices.
400      */
401     @RequiresFeature(PackageManager.FEATURE_USB_HOST)
getDeviceList()402     public HashMap<String,UsbDevice> getDeviceList() {
403         HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>();
404         if (mService == null) {
405             return result;
406         }
407         Bundle bundle = new Bundle();
408         try {
409             mService.getDeviceList(bundle);
410             for (String name : bundle.keySet()) {
411                 result.put(name, (UsbDevice)bundle.get(name));
412             }
413             return result;
414         } catch (RemoteException e) {
415             throw e.rethrowFromSystemServer();
416         }
417     }
418 
419     /**
420      * Opens the device so it can be used to send and receive
421      * data using {@link android.hardware.usb.UsbRequest}.
422      *
423      * @param device the device to open
424      * @return a {@link UsbDeviceConnection}, or {@code null} if open failed
425      */
426     @RequiresFeature(PackageManager.FEATURE_USB_HOST)
openDevice(UsbDevice device)427     public UsbDeviceConnection openDevice(UsbDevice device) {
428         try {
429             String deviceName = device.getDeviceName();
430             ParcelFileDescriptor pfd = mService.openDevice(deviceName, mContext.getPackageName());
431             if (pfd != null) {
432                 UsbDeviceConnection connection = new UsbDeviceConnection(device);
433                 boolean result = connection.open(deviceName, pfd, mContext);
434                 pfd.close();
435                 if (result) {
436                     return connection;
437                 }
438             }
439         } catch (Exception e) {
440             Log.e(TAG, "exception in UsbManager.openDevice", e);
441         }
442         return null;
443     }
444 
445     /**
446      * Returns a list of currently attached USB accessories.
447      * (in the current implementation there can be at most one)
448      *
449      * @return list of USB accessories, or null if none are attached.
450      */
451     @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
getAccessoryList()452     public UsbAccessory[] getAccessoryList() {
453         if (mService == null) {
454             return null;
455         }
456         try {
457             UsbAccessory accessory = mService.getCurrentAccessory();
458             if (accessory == null) {
459                 return null;
460             } else {
461                 return new UsbAccessory[] { accessory };
462             }
463         } catch (RemoteException e) {
464             throw e.rethrowFromSystemServer();
465         }
466     }
467 
468     /**
469      * Opens a file descriptor for reading and writing data to the USB accessory.
470      *
471      * <p>If data is read from the {@link java.io.InputStream} created from this file descriptor all
472      * data of a USB transfer should be read at once. If only a partial request is read the rest of
473      * the transfer is dropped.
474      *
475      * @param accessory the USB accessory to open
476      * @return file descriptor, or null if the accessory could not be opened.
477      */
478     @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
openAccessory(UsbAccessory accessory)479     public ParcelFileDescriptor openAccessory(UsbAccessory accessory) {
480         try {
481             return mService.openAccessory(accessory);
482         } catch (RemoteException e) {
483             throw e.rethrowFromSystemServer();
484         }
485     }
486 
487     /**
488      * Gets the functionfs control file descriptor for the given function, with
489      * the usb descriptors and strings already written. The file descriptor is used
490      * by the function implementation to handle events and control requests.
491      *
492      * @param function to get control fd for. Currently {@link #FUNCTION_MTP} and
493      * {@link #FUNCTION_PTP} are supported.
494      * @return A ParcelFileDescriptor holding the valid fd, or null if the fd was not found.
495      *
496      * {@hide}
497      */
getControlFd(long function)498     public ParcelFileDescriptor getControlFd(long function) {
499         try {
500             return mService.getControlFd(function);
501         } catch (RemoteException e) {
502             throw e.rethrowFromSystemServer();
503         }
504     }
505 
506     /**
507      * Returns true if the caller has permission to access the device.
508      * Permission might have been granted temporarily via
509      * {@link #requestPermission(UsbDevice, PendingIntent)} or
510      * by the user choosing the caller as the default application for the device.
511      * Permission for USB devices of class {@link UsbConstants#USB_CLASS_VIDEO} for clients that
512      * target SDK {@link android.os.Build.VERSION_CODES#P} and above can be granted only if they
513      * have additionally the {@link android.Manifest.permission#CAMERA} permission.
514      *
515      * @param device to check permissions for
516      * @return true if caller has permission
517      */
518     @RequiresFeature(PackageManager.FEATURE_USB_HOST)
hasPermission(UsbDevice device)519     public boolean hasPermission(UsbDevice device) {
520         if (mService == null) {
521             return false;
522         }
523         try {
524             return mService.hasDevicePermission(device, mContext.getPackageName());
525         } catch (RemoteException e) {
526             throw e.rethrowFromSystemServer();
527         }
528     }
529 
530     /**
531      * Returns true if the caller has permission to access the accessory.
532      * Permission might have been granted temporarily via
533      * {@link #requestPermission(UsbAccessory, PendingIntent)} or
534      * by the user choosing the caller as the default application for the accessory.
535      *
536      * @param accessory to check permissions for
537      * @return true if caller has permission
538      */
539     @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
hasPermission(UsbAccessory accessory)540     public boolean hasPermission(UsbAccessory accessory) {
541         if (mService == null) {
542             return false;
543         }
544         try {
545             return mService.hasAccessoryPermission(accessory);
546         } catch (RemoteException e) {
547             throw e.rethrowFromSystemServer();
548         }
549     }
550 
551     /**
552      * Requests temporary permission for the given package to access the device.
553      * This may result in a system dialog being displayed to the user
554      * if permission had not already been granted.
555      * Success or failure is returned via the {@link android.app.PendingIntent} pi.
556      * If successful, this grants the caller permission to access the device only
557      * until the device is disconnected.
558      *
559      * The following extras will be added to pi:
560      * <ul>
561      * <li> {@link #EXTRA_DEVICE} containing the device passed into this call
562      * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether
563      * permission was granted by the user
564      * </ul>
565      *
566      * Permission for USB devices of class {@link UsbConstants#USB_CLASS_VIDEO} for clients that
567      * target SDK {@link android.os.Build.VERSION_CODES#P} and above can be granted only if they
568      * have additionally the {@link android.Manifest.permission#CAMERA} permission.
569      *
570      * @param device to request permissions for
571      * @param pi PendingIntent for returning result
572      */
573     @RequiresFeature(PackageManager.FEATURE_USB_HOST)
requestPermission(UsbDevice device, PendingIntent pi)574     public void requestPermission(UsbDevice device, PendingIntent pi) {
575         try {
576             mService.requestDevicePermission(device, mContext.getPackageName(), pi);
577         } catch (RemoteException e) {
578             throw e.rethrowFromSystemServer();
579         }
580     }
581 
582     /**
583      * Requests temporary permission for the given package to access the accessory.
584      * This may result in a system dialog being displayed to the user
585      * if permission had not already been granted.
586      * Success or failure is returned via the {@link android.app.PendingIntent} pi.
587      * If successful, this grants the caller permission to access the accessory only
588      * until the device is disconnected.
589      *
590      * The following extras will be added to pi:
591      * <ul>
592      * <li> {@link #EXTRA_ACCESSORY} containing the accessory passed into this call
593      * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether
594      * permission was granted by the user
595      * </ul>
596      *
597      * @param accessory to request permissions for
598      * @param pi PendingIntent for returning result
599      */
600     @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY)
requestPermission(UsbAccessory accessory, PendingIntent pi)601     public void requestPermission(UsbAccessory accessory, PendingIntent pi) {
602         try {
603             mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi);
604         } catch (RemoteException e) {
605             throw e.rethrowFromSystemServer();
606         }
607     }
608 
609     /**
610      * Grants permission for USB device without showing system dialog.
611      * Only system components can call this function.
612      * @param device to request permissions for
613      *
614      * {@hide}
615      */
grantPermission(UsbDevice device)616     public void grantPermission(UsbDevice device) {
617         grantPermission(device, Process.myUid());
618     }
619 
620     /**
621      * Grants permission for USB device to given uid without showing system dialog.
622      * Only system components can call this function.
623      * @param device to request permissions for
624      * @uid uid to give permission
625      *
626      * {@hide}
627      */
grantPermission(UsbDevice device, int uid)628     public void grantPermission(UsbDevice device, int uid) {
629         try {
630             mService.grantDevicePermission(device, uid);
631         } catch (RemoteException e) {
632             throw e.rethrowFromSystemServer();
633         }
634     }
635 
636     /**
637      * Grants permission to specified package for USB device without showing system dialog.
638      * Only system components can call this function, as it requires the MANAGE_USB permission.
639      * @param device to request permissions for
640      * @param packageName of package to grant permissions
641      *
642      * {@hide}
643      */
644     @SystemApi
645     @RequiresPermission(Manifest.permission.MANAGE_USB)
grantPermission(UsbDevice device, String packageName)646     public void grantPermission(UsbDevice device, String packageName) {
647         try {
648             int uid = mContext.getPackageManager()
649                 .getPackageUidAsUser(packageName, mContext.getUserId());
650             grantPermission(device, uid);
651         } catch (NameNotFoundException e) {
652             Log.e(TAG, "Package " + packageName + " not found.", e);
653         }
654     }
655 
656     /**
657      * Returns true if the specified USB function is currently enabled when in device mode.
658      * <p>
659      * USB functions represent interfaces which are published to the host to access
660      * services offered by the device.
661      * </p>
662      *
663      * @deprecated use getCurrentFunctions() instead.
664      * @param function name of the USB function
665      * @return true if the USB function is enabled
666      *
667      * {@hide}
668      */
669     @Deprecated
670     @UnsupportedAppUsage
isFunctionEnabled(String function)671     public boolean isFunctionEnabled(String function) {
672         try {
673             return mService.isFunctionEnabled(function);
674         } catch (RemoteException e) {
675             throw e.rethrowFromSystemServer();
676         }
677     }
678 
679     /**
680      * Sets the current USB functions when in device mode.
681      * <p>
682      * USB functions represent interfaces which are published to the host to access
683      * services offered by the device.
684      * </p><p>
685      * This method is intended to select among primary USB functions.  The system may
686      * automatically activate additional functions such as {@link #USB_FUNCTION_ADB}
687      * or {@link #USB_FUNCTION_ACCESSORY} based on other settings and states.
688      * </p><p>
689      * An argument of 0 indicates that the device is charging, and can pick any
690      * appropriate function for that purpose.
691      * </p><p>
692      * Note: This function is asynchronous and may fail silently without applying
693      * the requested changes.
694      * </p>
695      *
696      * @param functions the USB function(s) to set, as a bitwise mask.
697      *                  Must satisfy {@link UsbManager#areSettableFunctions}
698      *
699      * {@hide}
700      */
setCurrentFunctions(long functions)701     public void setCurrentFunctions(long functions) {
702         try {
703             mService.setCurrentFunctions(functions);
704         } catch (RemoteException e) {
705             throw e.rethrowFromSystemServer();
706         }
707     }
708 
709     /**
710      * Sets the current USB functions when in device mode.
711      *
712      * @deprecated use setCurrentFunctions(long) instead.
713      * @param functions the USB function(s) to set.
714      * @param usbDataUnlocked unused
715 
716      * {@hide}
717      */
718     @Deprecated
719     @UnsupportedAppUsage
setCurrentFunction(String functions, boolean usbDataUnlocked)720     public void setCurrentFunction(String functions, boolean usbDataUnlocked) {
721         try {
722             mService.setCurrentFunction(functions, usbDataUnlocked);
723         } catch (RemoteException e) {
724             throw e.rethrowFromSystemServer();
725         }
726     }
727 
728     /**
729      * Returns the current USB functions in device mode.
730      * <p>
731      * This function returns the state of primary USB functions and can return a
732      * mask containing any usb function(s) except for ADB.
733      * </p>
734      *
735      * @return The currently enabled functions, in a bitwise mask.
736      * A zero mask indicates that the current function is the charging function.
737      *
738      * {@hide}
739      */
getCurrentFunctions()740     public long getCurrentFunctions() {
741         try {
742             return mService.getCurrentFunctions();
743         } catch (RemoteException e) {
744             throw e.rethrowFromSystemServer();
745         }
746     }
747 
748     /**
749      * Sets the screen unlocked functions, which are persisted and set as the current functions
750      * whenever the screen is unlocked.
751      * <p>
752      * A zero mask has the effect of switching off this feature, so functions
753      * no longer change on screen unlock.
754      * </p><p>
755      * Note: When the screen is on, this method will apply given functions as current functions,
756      * which is asynchronous and may fail silently without applying the requested changes.
757      * </p>
758      *
759      * @param functions functions to set, in a bitwise mask.
760      *                  Must satisfy {@link UsbManager#areSettableFunctions}
761      *
762      * {@hide}
763      */
setScreenUnlockedFunctions(long functions)764     public void setScreenUnlockedFunctions(long functions) {
765         try {
766             mService.setScreenUnlockedFunctions(functions);
767         } catch (RemoteException e) {
768             throw e.rethrowFromSystemServer();
769         }
770     }
771 
772     /**
773      * Gets the current screen unlocked functions.
774      *
775      * @return The currently set screen enabled functions.
776      * A zero mask indicates that the screen unlocked functions feature is not enabled.
777      *
778      * {@hide}
779      */
getScreenUnlockedFunctions()780     public long getScreenUnlockedFunctions() {
781         try {
782             return mService.getScreenUnlockedFunctions();
783         } catch (RemoteException e) {
784             throw e.rethrowFromSystemServer();
785         }
786     }
787 
788     /**
789      * Returns a list of physical USB ports on the device.
790      * <p>
791      * This list is guaranteed to contain all dual-role USB Type C ports but it might
792      * be missing other ports depending on whether the kernel USB drivers have been
793      * updated to publish all of the device's ports through the new "dual_role_usb"
794      * device class (which supports all types of ports despite its name).
795      * </p>
796      *
797      * @return The list of USB ports
798      *
799      * @hide
800      */
801     @SystemApi
802     @RequiresPermission(Manifest.permission.MANAGE_USB)
getPorts()803     public @NonNull List<UsbPort> getPorts() {
804         if (mService == null) {
805             return Collections.emptyList();
806         }
807 
808         List<ParcelableUsbPort> parcelablePorts;
809         try {
810             parcelablePorts = mService.getPorts();
811         } catch (RemoteException e) {
812             throw e.rethrowFromSystemServer();
813         }
814 
815         if (parcelablePorts == null) {
816             return Collections.emptyList();
817         } else {
818             int numPorts = parcelablePorts.size();
819 
820             ArrayList<UsbPort> ports = new ArrayList<>(numPorts);
821             for (int i = 0; i < numPorts; i++) {
822                 ports.add(parcelablePorts.get(i).getUsbPort(this));
823             }
824 
825             return ports;
826         }
827     }
828 
829     /**
830      * Should only be called by {@link UsbPort#getStatus}.
831      *
832      * @hide
833      */
getPortStatus(UsbPort port)834     UsbPortStatus getPortStatus(UsbPort port) {
835         try {
836             return mService.getPortStatus(port.getId());
837         } catch (RemoteException e) {
838             throw e.rethrowFromSystemServer();
839         }
840     }
841 
842     /**
843      * Should only be called by {@link UsbPort#setRoles}.
844      *
845      * @hide
846      */
setPortRoles(UsbPort port, int powerRole, int dataRole)847     void setPortRoles(UsbPort port, int powerRole, int dataRole) {
848         Log.d(TAG, "setPortRoles Package:" + mContext.getPackageName());
849         try {
850             mService.setPortRoles(port.getId(), powerRole, dataRole);
851         } catch (RemoteException e) {
852             throw e.rethrowFromSystemServer();
853         }
854     }
855 
856     /**
857      * Enables USB port contaminant detection algorithm.
858      *
859      * @hide
860      */
861     @RequiresPermission(Manifest.permission.MANAGE_USB)
enableContaminantDetection(@onNull UsbPort port, boolean enable)862     void enableContaminantDetection(@NonNull UsbPort port, boolean enable) {
863         try {
864             mService.enableContaminantDetection(port.getId(), enable);
865         } catch (RemoteException e) {
866             throw e.rethrowFromSystemServer();
867         }
868     }
869 
870     /**
871      * Sets the component that will handle USB device connection.
872      * <p>
873      * Setting component allows to specify external USB host manager to handle use cases, where
874      * selection dialog for an activity that will handle USB device is undesirable.
875      * Only system components can call this function, as it requires the MANAGE_USB permission.
876      *
877      * @param usbDeviceConnectionHandler The component to handle usb connections,
878      * {@code null} to unset.
879      *
880      * {@hide}
881      */
setUsbDeviceConnectionHandler(@ullable ComponentName usbDeviceConnectionHandler)882     public void setUsbDeviceConnectionHandler(@Nullable ComponentName usbDeviceConnectionHandler) {
883         try {
884             mService.setUsbDeviceConnectionHandler(usbDeviceConnectionHandler);
885         } catch (RemoteException e) {
886             throw e.rethrowFromSystemServer();
887         }
888     }
889 
890     /**
891      * Returns whether the given functions are valid inputs to UsbManager.
892      * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI are accepted.
893      *
894      * @return Whether the mask is settable.
895      *
896      * {@hide}
897      */
areSettableFunctions(long functions)898     public static boolean areSettableFunctions(long functions) {
899         return functions == FUNCTION_NONE
900                 || ((~SETTABLE_FUNCTIONS & functions) == 0 && Long.bitCount(functions) == 1);
901     }
902 
903     /**
904      * Converts the given function mask to string. Maintains ordering with respect to init scripts.
905      *
906      * @return String representation of given mask
907      *
908      * {@hide}
909      */
usbFunctionsToString(long functions)910     public static String usbFunctionsToString(long functions) {
911         StringJoiner joiner = new StringJoiner(",");
912         if ((functions & FUNCTION_MTP) != 0) {
913             joiner.add(UsbManager.USB_FUNCTION_MTP);
914         }
915         if ((functions & FUNCTION_PTP) != 0) {
916             joiner.add(UsbManager.USB_FUNCTION_PTP);
917         }
918         if ((functions & FUNCTION_RNDIS) != 0) {
919             joiner.add(UsbManager.USB_FUNCTION_RNDIS);
920         }
921         if ((functions & FUNCTION_MIDI) != 0) {
922             joiner.add(UsbManager.USB_FUNCTION_MIDI);
923         }
924         if ((functions & FUNCTION_ACCESSORY) != 0) {
925             joiner.add(UsbManager.USB_FUNCTION_ACCESSORY);
926         }
927         if ((functions & FUNCTION_AUDIO_SOURCE) != 0) {
928             joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE);
929         }
930         if ((functions & FUNCTION_ADB) != 0) {
931             joiner.add(UsbManager.USB_FUNCTION_ADB);
932         }
933         return joiner.toString();
934     }
935 
936     /**
937      * Parses a string of usb functions that are comma separated.
938      *
939      * @return A mask of all valid functions in the string
940      *
941      * {@hide}
942      */
usbFunctionsFromString(String functions)943     public static long usbFunctionsFromString(String functions) {
944         if (functions == null || functions.equals(USB_FUNCTION_NONE)) {
945             return FUNCTION_NONE;
946         }
947         long ret = 0;
948         for (String function : functions.split(",")) {
949             if (FUNCTION_NAME_TO_CODE.containsKey(function)) {
950                 ret |= FUNCTION_NAME_TO_CODE.get(function);
951             } else if (function.length() > 0) {
952                 throw new IllegalArgumentException("Invalid usb function " + functions);
953             }
954         }
955         return ret;
956     }
957 }
958