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