/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.hardware.usb; import static android.hardware.usb.UsbPortStatus.DATA_STATUS_DISABLED_FORCE; import android.Manifest; import android.annotation.CallbackExecutor; import android.annotation.IntDef; import android.annotation.LongDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresFeature; import android.annotation.RequiresPermission; import android.annotation.SdkConstant; import android.annotation.SdkConstant.SdkConstantType; import android.annotation.SystemApi; import android.annotation.SystemService; import android.app.PendingIntent; import android.compat.annotation.UnsupportedAppUsage; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; import android.hardware.usb.gadget.GadgetFunction; import android.hardware.usb.gadget.UsbSpeed; import android.os.Binder; import android.os.Build; import android.os.Bundle; import android.os.ParcelFileDescriptor; import android.os.Process; import android.os.RemoteException; import android.os.SystemProperties; import android.util.ArrayMap; import android.util.Log; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.StringJoiner; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicInteger; /** * This class allows you to access the state of USB and communicate with USB devices. * Currently only host mode is supported in the public API. * *
*

Developer Guides

*

For more information about communicating with USB hardware, read the * USB developer guide.

*
*/ @SystemService(Context.USB_SERVICE) public class UsbManager { private static final String TAG = "UsbManager"; /** * Broadcast Action: A sticky broadcast for USB state change events when in device mode. * * This is a sticky broadcast for clients that includes USB connected/disconnected state, * * If the sticky intent has not been found, that indicates USB is disconnected, * USB is not configured, MTP function is enabled, and all the other functions are disabled. * * @hide */ @SystemApi public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; /** * Broadcast Action: A broadcast for USB port changes. * * This intent is sent when a USB port is added, removed, or changes state. * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED"; /** * Broadcast Action: A broadcast for USB compliance warning changes. * * This intent is sent when a port partner's * (USB power source/cable/accessory) compliance warnings change state. * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_COMPLIANCE_CHANGED = "android.hardware.usb.action.USB_PORT_COMPLIANCE_CHANGED"; /** * Activity intent sent when user attaches a USB device. * * This intent is sent when a USB device is attached to the USB bus when in host mode. * */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_USB_DEVICE_ATTACHED = "android.hardware.usb.action.USB_DEVICE_ATTACHED"; /** * Broadcast Action: A broadcast for USB device detached event. * * This intent is sent when a USB device is detached from the USB bus when in host mode. * */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_USB_DEVICE_DETACHED = "android.hardware.usb.action.USB_DEVICE_DETACHED"; /** * Activity intent sent when user attaches a USB accessory. * * */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_USB_ACCESSORY_ATTACHED = "android.hardware.usb.action.USB_ACCESSORY_ATTACHED"; /** * Broadcast Action: A broadcast for USB accessory detached event. * * This intent is sent when a USB accessory is detached. * */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_USB_ACCESSORY_DETACHED = "android.hardware.usb.action.USB_ACCESSORY_DETACHED"; /** * Broadcast Action: A broadcast for USB accessory handshaking information delivery * * This intent is sent when a USB accessory connect attempt * *

For more information about communicating with USB accessory handshake, refer to * AOA developer guide.

* * @hide */ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public static final String ACTION_USB_ACCESSORY_HANDSHAKE = "android.hardware.usb.action.USB_ACCESSORY_HANDSHAKE"; /** * Boolean extra indicating whether USB is connected or disconnected. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. * * @hide */ @SystemApi public static final String USB_CONNECTED = "connected"; /** * Boolean extra indicating whether USB is connected or disconnected as host. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. * * @hide */ public static final String USB_HOST_CONNECTED = "host_connected"; /** * Boolean extra indicating whether USB is configured. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. * * @hide */ @SystemApi public static final String USB_CONFIGURED = "configured"; /** * Boolean extra indicating whether confidential user data, such as photos, should be * made available on the USB connection. This variable will only be set when the user * has explicitly asked for this data to be unlocked. * Used in extras for the {@link #ACTION_USB_STATE} broadcast. * * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public static final String USB_DATA_UNLOCKED = "unlocked"; /** * A placeholder indicating that no USB function is being specified. * Used for compatibility with old init scripts to indicate no functions vs. charging function. * * @hide */ @UnsupportedAppUsage public static final String USB_FUNCTION_NONE = "none"; /** * Name of the adb USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_ADB = "adb"; /** * Name of the RNDIS ethernet USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ @SystemApi public static final String USB_FUNCTION_RNDIS = "rndis"; /** * Name of the MTP USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_MTP = "mtp"; /** * Name of the PTP USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_PTP = "ptp"; /** * Name of the audio source USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_AUDIO_SOURCE = "audio_source"; /** * Name of the MIDI USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_MIDI = "midi"; /** * Name of the Accessory USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_ACCESSORY = "accessory"; /** * Name of the NCM USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ @SystemApi public static final String USB_FUNCTION_NCM = "ncm"; /** * Name of the UVC USB function. * Used in extras for the {@link #ACTION_USB_STATE} broadcast * * @hide */ public static final String USB_FUNCTION_UVC = "uvc"; /** * Name of Gadget Hal Not Present; * * @hide */ public static final String GADGET_HAL_UNKNOWN = "unknown"; /** * Name of the USB Gadget Hal Version v1.0; * * @hide */ public static final String GADGET_HAL_VERSION_1_0 = "V1_0"; /** * Name of the USB Gadget Hal Version v1.1; * * @hide */ public static final String GADGET_HAL_VERSION_1_1 = "V1_1"; /** * Name of the USB Gadget Hal Version v1.2; * * @hide */ public static final String GADGET_HAL_VERSION_1_2 = "V1_2"; /** * Name of the USB Gadget Hal Version v2.0; * * @hide */ public static final String GADGET_HAL_VERSION_2_0 = "V2_0"; /** * Name of extra for {@link #ACTION_USB_PORT_CHANGED} * containing the {@link UsbPort} object for the port. * * @hide */ public static final String EXTRA_PORT = "port"; /** * Name of extra for {@link #ACTION_USB_PORT_CHANGED} * containing the {@link UsbPortStatus} object for the port, or null if the port * was removed. * * @hide */ public static final String EXTRA_PORT_STATUS = "portStatus"; /** * Name of extra for {@link #ACTION_USB_DEVICE_ATTACHED} and * {@link #ACTION_USB_DEVICE_DETACHED} broadcasts * containing the {@link UsbDevice} object for the device. */ public static final String EXTRA_DEVICE = "device"; /** * Name of extra for {@link #ACTION_USB_ACCESSORY_ATTACHED} and * {@link #ACTION_USB_ACCESSORY_DETACHED} broadcasts * containing the {@link UsbAccessory} object for the accessory. */ public static final String EXTRA_ACCESSORY = "accessory"; /** * A long extra indicating ms from boot to get get_protocol UEvent * This is obtained with SystemClock.elapsedRealtime() * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts. * * @hide */ @SystemApi public static final String EXTRA_ACCESSORY_UEVENT_TIME = "android.hardware.usb.extra.ACCESSORY_UEVENT_TIME"; /** * An integer extra indicating numbers of send string during handshake * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts * *

For more information about control request with identifying string information * between communicating with USB accessory handshake, refer to * AOA developer guide.

* * @hide */ @SystemApi public static final String EXTRA_ACCESSORY_STRING_COUNT = "android.hardware.usb.extra.ACCESSORY_STRING_COUNT"; /** * Boolean extra indicating whether got start accessory or not * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts. * * @hide */ @SystemApi public static final String EXTRA_ACCESSORY_START = "android.hardware.usb.extra.ACCESSORY_START"; /** * A long extra indicating the timestamp just before * sending {@link #ACTION_USB_ACCESSORY_HANDSHAKE}. * Used in extras for {@link #ACTION_USB_ACCESSORY_HANDSHAKE} broadcasts. * * @hide */ @SystemApi public static final String EXTRA_ACCESSORY_HANDSHAKE_END = "android.hardware.usb.extra.ACCESSORY_HANDSHAKE_END"; /** * Name of extra added to the {@link android.app.PendingIntent} * passed into {@link #requestPermission(UsbDevice, PendingIntent)} * or {@link #requestPermission(UsbAccessory, PendingIntent)} * containing a boolean value indicating whether the user granted permission or not. */ public static final String EXTRA_PERMISSION_GRANTED = "permission"; /** * Name of extra added to start systemui.usb.UsbPermissionActivity * containing package name of the app which requests USB permission. * * @hide */ public static final String EXTRA_PACKAGE = "android.hardware.usb.extra.PACKAGE"; /** * Name of extra added to start systemui.usb.UsbPermissionActivity * containing the whether the app which requests USB permission can be set as default handler * for USB device attach event or USB accessory attach event or not. * * @hide */ public static final String EXTRA_CAN_BE_DEFAULT = "android.hardware.usb.extra.CAN_BE_DEFAULT"; /** * The Value for USB gadget hal is not presented. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int GADGET_HAL_NOT_SUPPORTED = -1; /** * Value for Gadget Hal Version v1.0. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int GADGET_HAL_V1_0 = 10; /** * Value for Gadget Hal Version v1.1. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int GADGET_HAL_V1_1 = 11; /** * Value for Gadget Hal Version v1.2. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int GADGET_HAL_V1_2 = 12; /** * Value for Gadget Hal Version v2.0. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int GADGET_HAL_V2_0 = 20; /** * Value for USB_STATE is not configured. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_UNKNOWN = -1; /** * Value for USB Transfer Rate of Low Speed in Mbps (real value is 1.5Mbps). * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_LOW_SPEED = 2; /** * Value for USB Transfer Rate of Full Speed in Mbps. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_FULL_SPEED = 12; /** * Value for USB Transfer Rate of High Speed in Mbps. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_HIGH_SPEED = 480; /** * Value for USB Transfer Rate of Super Speed in Mbps. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_5G = 5 * 1024; /** * Value for USB Transfer Rate of 10G. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_10G = 10 * 1024; /** * Value for USB Transfer Rate of 20G. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_20G = 20 * 1024; /** * Value for USB Transfer Rate of 40G. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_DATA_TRANSFER_RATE_40G = 40 * 1024; /** * Returned when the client has to retry querying the version. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_RETRY = -2; /** * The Value for USB hal is not presented. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_NOT_SUPPORTED = -1; /** * Value for USB Hal Version v1.0. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_V1_0 = 10; /** * Value for USB Hal Version v1.1. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_V1_1 = 11; /** * Value for USB Hal Version v1.2. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_V1_2 = 12; /** * Value for USB Hal Version v1.3. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_V1_3 = 13; /** * Value for USB Hal Version v2.0. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) public static final int USB_HAL_V2_0 = 20; /** * Code for the charging usb function. Passed into {@link #setCurrentFunctions(long)} * Must be equal to {@link GadgetFunction#NONE} * @hide */ @SystemApi public static final long FUNCTION_NONE = 0; /** * Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)} * Must be equal to {@link GadgetFunction#MTP} * @hide */ @SystemApi public static final long FUNCTION_MTP = 1 << 2; /** * Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)} * Must be equal to {@link GadgetFunction#PTP} * @hide */ @SystemApi public static final long FUNCTION_PTP = 1 << 4; /** * Code for the rndis usb function. Passed as a mask into {@link #setCurrentFunctions(long)} * Must be equal to {@link GadgetFunction#RNDIS} * @hide */ @SystemApi public static final long FUNCTION_RNDIS = 1 << 5; /** * Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)} * Must be equal to {@link GadgetFunction#MIDI} * @hide */ @SystemApi public static final long FUNCTION_MIDI = 1 << 3; /** * Code for the accessory usb function. * Must be equal to {@link GadgetFunction#ACCESSORY} * @hide */ @SystemApi public static final long FUNCTION_ACCESSORY = 1 << 1; /** * Code for the audio source usb function. * Must be equal to {@link GadgetFunction#AUDIO_SOURCE} * @hide */ @SystemApi public static final long FUNCTION_AUDIO_SOURCE = 1 << 6; /** * Code for the adb usb function. * Must be equal to {@link GadgetFunction#ADB} * @hide */ @SystemApi public static final long FUNCTION_ADB = 1; /** * Code for the ncm source usb function. * Must be equal to {@link GadgetFunction#NCM} * @hide */ @SystemApi public static final long FUNCTION_NCM = 1 << 10; /** * Code for the uvc usb function. Passed as a mask into {@link #setCurrentFunctions(long)} * Only supported if {@link #isUvcSupportEnabled()} returns true. * Must be equal to {@link GadgetFunction#UVC} * @hide */ @SystemApi public static final long FUNCTION_UVC = 1 << 7; private static final long SETTABLE_FUNCTIONS = FUNCTION_MTP | FUNCTION_PTP | FUNCTION_RNDIS | FUNCTION_MIDI | FUNCTION_NCM | FUNCTION_UVC; private static final Map FUNCTION_NAME_TO_CODE = new HashMap<>(); /** * Counter for tracking UsbOperation operations. */ private static final AtomicInteger sUsbOperationCount = new AtomicInteger(); static { FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MTP, FUNCTION_MTP); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_PTP, FUNCTION_PTP); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_RNDIS, FUNCTION_RNDIS); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_MIDI, FUNCTION_MIDI); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ACCESSORY, FUNCTION_ACCESSORY); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_AUDIO_SOURCE, FUNCTION_AUDIO_SOURCE); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_ADB, FUNCTION_ADB); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM); FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_UVC, FUNCTION_UVC); } /** @hide */ @LongDef(flag = true, prefix = { "FUNCTION_" }, value = { FUNCTION_NONE, FUNCTION_MTP, FUNCTION_PTP, FUNCTION_RNDIS, FUNCTION_MIDI, FUNCTION_ACCESSORY, FUNCTION_AUDIO_SOURCE, FUNCTION_ADB, FUNCTION_NCM, FUNCTION_UVC, }) @Retention(RetentionPolicy.SOURCE) public @interface UsbFunctionMode {} /** @hide */ @IntDef(prefix = { "GADGET_HAL_" }, value = { GADGET_HAL_NOT_SUPPORTED, GADGET_HAL_V1_0, GADGET_HAL_V1_1, GADGET_HAL_V1_2, GADGET_HAL_V2_0, }) @Retention(RetentionPolicy.SOURCE) public @interface UsbGadgetHalVersion {} /** @hide */ @IntDef(prefix = { "USB_HAL_" }, value = { USB_HAL_NOT_SUPPORTED, USB_HAL_V1_0, USB_HAL_V1_1, USB_HAL_V1_2, USB_HAL_V1_3, USB_HAL_V2_0, }) @Retention(RetentionPolicy.SOURCE) public @interface UsbHalVersion {} /** * Listener to register for when the {@link DisplayPortAltModeInfo} changes on a * {@link UsbPort}. * * @hide */ @SystemApi public interface DisplayPortAltModeInfoListener { /** * Callback to be executed when the {@link DisplayPortAltModeInfo} changes on a * {@link UsbPort}. * * @param portId String describing the {@link UsbPort} that was changed. * @param info New {@link DisplayPortAltModeInfo} for the corresponding portId. */ public void onDisplayPortAltModeInfoChanged(@NonNull String portId, @NonNull DisplayPortAltModeInfo info); } /** * Holds callback and executor data to be passed across UsbService. */ private class DisplayPortAltModeInfoDispatchingListener extends IDisplayPortAltModeInfoListener.Stub { public void onDisplayPortAltModeInfoChanged(String portId, DisplayPortAltModeInfo displayPortAltModeInfo) { synchronized (mDisplayPortListenersLock) { for (Map.Entry entry : mDisplayPortListeners.entrySet()) { Executor executor = entry.getValue(); DisplayPortAltModeInfoListener callback = entry.getKey(); final long token = Binder.clearCallingIdentity(); try { executor.execute(() -> callback.onDisplayPortAltModeInfoChanged(portId, displayPortAltModeInfo)); } catch (Exception e) { Slog.e(TAG, "Exception during onDisplayPortAltModeInfoChanged from " + "executor: " + executor, e); } finally { Binder.restoreCallingIdentity(token); } } } } } private final Context mContext; private final IUsbManager mService; private final Object mDisplayPortListenersLock = new Object(); @GuardedBy("mDisplayPortListenersLock") private ArrayMap mDisplayPortListeners; @GuardedBy("mDisplayPortListenersLock") private DisplayPortAltModeInfoDispatchingListener mDisplayPortServiceListener; /** * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) public UsbManager(Context context, IUsbManager service) { mContext = context; mService = service; } /** * Returns a HashMap containing all USB devices currently attached. * USB device name is the key for the returned HashMap. * The result will be empty if no devices are attached, or if * USB host mode is inactive or unsupported. * * @return HashMap containing all connected USB devices. */ @RequiresFeature(PackageManager.FEATURE_USB_HOST) public HashMap getDeviceList() { HashMap result = new HashMap(); if (mService == null) { return result; } Bundle bundle = new Bundle(); try { mService.getDeviceList(bundle); for (String name : bundle.keySet()) { result.put(name, (UsbDevice)bundle.get(name)); } return result; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Opens the device so it can be used to send and receive * data using {@link android.hardware.usb.UsbRequest}. * * @param device the device to open * @return a {@link UsbDeviceConnection}, or {@code null} if open failed */ @RequiresFeature(PackageManager.FEATURE_USB_HOST) public UsbDeviceConnection openDevice(UsbDevice device) { try { String deviceName = device.getDeviceName(); ParcelFileDescriptor pfd = mService.openDevice(deviceName, mContext.getPackageName()); if (pfd != null) { UsbDeviceConnection connection = new UsbDeviceConnection(device); boolean result = connection.open(deviceName, pfd, mContext); pfd.close(); if (result) { return connection; } } } catch (Exception e) { Log.e(TAG, "exception in UsbManager.openDevice", e); } return null; } /** * Returns a list of currently attached USB accessories. * (in the current implementation there can be at most one) * * @return list of USB accessories, or null if none are attached. */ @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY) public UsbAccessory[] getAccessoryList() { if (mService == null) { return null; } try { UsbAccessory accessory = mService.getCurrentAccessory(); if (accessory == null) { return null; } else { return new UsbAccessory[] { accessory }; } } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Opens a file descriptor for reading and writing data to the USB accessory. * *

If data is read from the {@link java.io.InputStream} created from this file descriptor all * data of a USB transfer should be read at once. If only a partial request is read the rest of * the transfer is dropped. * * @param accessory the USB accessory to open * @return file descriptor, or null if the accessory could not be opened. */ @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY) public ParcelFileDescriptor openAccessory(UsbAccessory accessory) { try { return mService.openAccessory(accessory); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Gets the functionfs control file descriptor for the given function, with * the usb descriptors and strings already written. The file descriptor is used * by the function implementation to handle events and control requests. * * @param function to get control fd for. Currently {@link #FUNCTION_MTP} and * {@link #FUNCTION_PTP} are supported. * @return A ParcelFileDescriptor holding the valid fd, or null if the fd was not found. * * @hide */ public ParcelFileDescriptor getControlFd(long function) { try { return mService.getControlFd(function); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns true if the caller has permission to access the device. * Permission might have been granted temporarily via * {@link #requestPermission(UsbDevice, PendingIntent)} or * by the user choosing the caller as the default application for the device. * Permission for USB devices of class {@link UsbConstants#USB_CLASS_VIDEO} for clients that * target SDK {@link android.os.Build.VERSION_CODES#P} and above can be granted only if they * have additionally the {@link android.Manifest.permission#CAMERA} permission. * * @param device to check permissions for * @return true if caller has permission */ @RequiresFeature(PackageManager.FEATURE_USB_HOST) public boolean hasPermission(UsbDevice device) { if (mService == null) { return false; } try { return mService.hasDevicePermission(device, mContext.getPackageName()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns true if the caller has permission to access the device. It's similar to the * {@link #hasPermission(UsbDevice)} but allows to specify a different package/uid/pid. * *

Not for third-party apps.

* * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) @RequiresFeature(PackageManager.FEATURE_USB_HOST) public boolean hasPermission(@NonNull UsbDevice device, @NonNull String packageName, int pid, int uid) { if (mService == null) { return false; } try { return mService.hasDevicePermissionWithIdentity(device, packageName, pid, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns true if the caller has permission to access the accessory. * Permission might have been granted temporarily via * {@link #requestPermission(UsbAccessory, PendingIntent)} or * by the user choosing the caller as the default application for the accessory. * * @param accessory to check permissions for * @return true if caller has permission */ @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY) public boolean hasPermission(UsbAccessory accessory) { if (mService == null) { return false; } try { return mService.hasAccessoryPermission(accessory); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns true if the caller has permission to access the accessory. It's similar to the * {@link #hasPermission(UsbAccessory)} but allows to specify a different uid/pid. * *

Not for third-party apps.

* * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY) public boolean hasPermission(@NonNull UsbAccessory accessory, int pid, int uid) { if (mService == null) { return false; } try { return mService.hasAccessoryPermissionWithIdentity(accessory, pid, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Requests temporary permission for the given package to access the device. * This may result in a system dialog being displayed to the user * if permission had not already been granted. * Success or failure is returned via the {@link android.app.PendingIntent} pi. * If successful, this grants the caller permission to access the device only * until the device is disconnected. * * The following extras will be added to pi: *
    *
  • {@link #EXTRA_DEVICE} containing the device passed into this call *
  • {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether * permission was granted by the user *
* * Permission for USB devices of class {@link UsbConstants#USB_CLASS_VIDEO} for clients that * target SDK {@link android.os.Build.VERSION_CODES#P} and above can be granted only if they * have additionally the {@link android.Manifest.permission#CAMERA} permission. * * @param device to request permissions for * @param pi PendingIntent for returning result */ @RequiresFeature(PackageManager.FEATURE_USB_HOST) public void requestPermission(UsbDevice device, PendingIntent pi) { try { mService.requestDevicePermission(device, mContext.getPackageName(), pi); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Requests temporary permission for the given package to access the accessory. * This may result in a system dialog being displayed to the user * if permission had not already been granted. * Success or failure is returned via the {@link android.app.PendingIntent} pi. * If successful, this grants the caller permission to access the accessory only * until the device is disconnected. * * The following extras will be added to pi: *
    *
  • {@link #EXTRA_ACCESSORY} containing the accessory passed into this call *
  • {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether * permission was granted by the user *
* * @param accessory to request permissions for * @param pi PendingIntent for returning result */ @RequiresFeature(PackageManager.FEATURE_USB_ACCESSORY) public void requestPermission(UsbAccessory accessory, PendingIntent pi) { try { mService.requestAccessoryPermission(accessory, mContext.getPackageName(), pi); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Grants permission for USB device without showing system dialog. * Only system components can call this function. * @param device to request permissions for * * @hide */ public void grantPermission(UsbDevice device) { grantPermission(device, Process.myUid()); } /** * Grants permission for USB device to given uid without showing system dialog. * Only system components can call this function. * @param device to request permissions for * @uid uid to give permission * * @hide */ public void grantPermission(UsbDevice device, int uid) { try { mService.grantDevicePermission(device, uid); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Grants permission to specified package for USB device without showing system dialog. * Only system components can call this function, as it requires the MANAGE_USB permission. * @param device to request permissions for * @param packageName of package to grant permissions * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public void grantPermission(UsbDevice device, String packageName) { try { int uid = mContext.getPackageManager() .getPackageUidAsUser(packageName, mContext.getUserId()); grantPermission(device, uid); } catch (NameNotFoundException e) { Log.e(TAG, "Package " + packageName + " not found.", e); } } /** * Returns true if the specified USB function is currently enabled when in device mode. *

* USB functions represent interfaces which are published to the host to access * services offered by the device. *

* * @deprecated use getCurrentFunctions() instead. * @param function name of the USB function * @return true if the USB function is enabled * * @hide */ @Deprecated @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public boolean isFunctionEnabled(String function) { try { return mService.isFunctionEnabled(function); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Sets the current USB functions when in device mode. *

* USB functions represent interfaces which are published to the host to access * services offered by the device. *

* This method is intended to select among primary USB functions. The system may * automatically activate additional functions such as {@link #USB_FUNCTION_ADB} * or {@link #USB_FUNCTION_ACCESSORY} based on other settings and states. *

* An argument of 0 indicates that the device is charging, and can pick any * appropriate function for that purpose. *

* Note: This function is asynchronous and may fail silently without applying * the requested changes. *

* * @param functions the USB function(s) to set, as a bitwise mask. * Must satisfy {@link UsbManager#areSettableFunctions} * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public void setCurrentFunctions(@UsbFunctionMode long functions) { int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); try { mService.setCurrentFunctions(functions, operationId); } catch (RemoteException e) { Log.e(TAG, "setCurrentFunctions: failed to call setCurrentFunctions. functions:" + functions + ", opId:" + operationId, e); throw e.rethrowFromSystemServer(); } } /** * Sets the current USB functions when in device mode. * * @deprecated use setCurrentFunctions(long) instead. * @param functions the USB function(s) to set. * @param usbDataUnlocked unused * @hide */ @Deprecated @UnsupportedAppUsage public void setCurrentFunction(String functions, boolean usbDataUnlocked) { int operationId = sUsbOperationCount.incrementAndGet() + Binder.getCallingUid(); try { mService.setCurrentFunction(functions, usbDataUnlocked, operationId); } catch (RemoteException e) { Log.e(TAG, "setCurrentFunction: failed to call setCurrentFunction. functions:" + functions + ", opId:" + operationId, e); throw e.rethrowFromSystemServer(); } } /** * Returns the current USB functions in device mode. *

* This function returns the state of primary USB functions and can return a * mask containing any usb function(s) except for ADB. *

* * @return The currently enabled functions, in a bitwise mask. * A zero mask indicates that the current function is the charging function. * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public long getCurrentFunctions() { try { return mService.getCurrentFunctions(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Sets the screen unlocked functions, which are persisted and set as the current functions * whenever the screen is unlocked. *

* A zero mask has the effect of switching off this feature, so functions * no longer change on screen unlock. *

* Note: When the screen is on, this method will apply given functions as current functions, * which is asynchronous and may fail silently without applying the requested changes. *

* * @param functions functions to set, in a bitwise mask. * Must satisfy {@link UsbManager#areSettableFunctions} * * @hide */ public void setScreenUnlockedFunctions(long functions) { try { mService.setScreenUnlockedFunctions(functions); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Gets the current screen unlocked functions. * * @return The currently set screen enabled functions. * A zero mask indicates that the screen unlocked functions feature is not enabled. * * @hide */ public long getScreenUnlockedFunctions() { try { return mService.getScreenUnlockedFunctions(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Get the Current USB Bandwidth. *

* This function returns the current USB bandwidth through USB Gadget HAL. * It should be used when Android device is in USB peripheral mode and * connects to a USB host. If USB state is not configued, API will return * {@value #USB_DATA_TRANSFER_RATE_UNKNOWN}. In addition, the unit of the * return value is Mbps. *

* * @return The value of currently USB Bandwidth. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MANAGE_USB) public int getUsbBandwidthMbps() { int usbSpeed; try { usbSpeed = mService.getCurrentUsbSpeed(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } return usbSpeedToBandwidth(usbSpeed); } /** * Get the Current Gadget Hal Version. *

* This function returns the current Gadget Hal Version. *

* * @return a integer {@code GADGET_HAL_*} represent hal version. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MANAGE_USB) public @UsbGadgetHalVersion int getGadgetHalVersion() { try { return mService.getGadgetHalVersion(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Get the Current USB Hal Version. *

* This function returns the current USB Hal Version. *

* * @return a integer {@code USB_HAL_*} represent hal version. * * @hide */ @SystemApi(client = SystemApi.Client.MODULE_LIBRARIES) @RequiresPermission(Manifest.permission.MANAGE_USB) public @UsbHalVersion int getUsbHalVersion() { try { return mService.getUsbHalVersion(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Resets the USB Gadget. *

* Performs USB data stack reset through USB Gadget HAL. * It will force USB data connection reset. The connection will disconnect and reconnect. *

* * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public void resetUsbGadget() { try { mService.resetUsbGadget(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns whether UVC is advertised to be supported or not. SELinux * enforces that this function returns {@code false} when called from a * process that doesn't belong either to a system app, or the * DeviceAsWebcam Service. * * @return true if UVC is supported, false if UVC is not supported or if * called from a non-system app that isn't DeviceAsWebcam Service. * @hide */ @SystemApi public static boolean isUvcSupportEnabled() { return SystemProperties.getBoolean("ro.usb.uvc.enabled", false); } /** * Enable/Disable the USB data signaling. *

* Enables/Disables USB data path of all USB ports. * It will force to stop or restore USB data signaling. *

* * @param enable enable or disable USB data signaling * @return true enable or disable USB data successfully * false if something wrong * * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) public boolean enableUsbDataSignal(boolean enable) { return setUsbDataSignal(getPorts(), !enable, /* revertOnFailure= */ true); } private boolean setUsbDataSignal(List usbPorts, boolean disable, boolean revertOnFailure) { List changedPorts = new ArrayList<>(); for (int i = 0; i < usbPorts.size(); i++) { UsbPort port = usbPorts.get(i); if (isPortDisabled(port) != disable) { changedPorts.add(port); if (port.enableUsbData(!disable) != UsbPort.ENABLE_USB_DATA_SUCCESS && revertOnFailure) { Log.e(TAG, "Failed to set usb data signal for portID(" + port.getId() + ")"); setUsbDataSignal(changedPorts, !disable, /* revertOnFailure= */ false); return false; } } } return true; } private boolean isPortDisabled(UsbPort usbPort) { return (getPortStatus(usbPort).getUsbDataStatus() & DATA_STATUS_DISABLED_FORCE) == DATA_STATUS_DISABLED_FORCE; } /** * Returns a list of physical USB ports on the device. *

* This list is guaranteed to contain all dual-role USB Type C ports but it might * be missing other ports depending on whether the kernel USB drivers have been * updated to publish all of the device's ports through the new "dual_role_usb" * device class (which supports all types of ports despite its name). *

* * @return The list of USB ports * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public @NonNull List getPorts() { if (mService == null) { return Collections.emptyList(); } List parcelablePorts; try { parcelablePorts = mService.getPorts(); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } if (parcelablePorts == null) { return Collections.emptyList(); } else { int numPorts = parcelablePorts.size(); ArrayList ports = new ArrayList<>(numPorts); for (int i = 0; i < numPorts; i++) { ports.add(parcelablePorts.get(i).getUsbPort(this)); } return ports; } } /** * Should only be called by {@link UsbPort#getStatus}. * * @hide */ UsbPortStatus getPortStatus(UsbPort port) { try { return mService.getPortStatus(port.getId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Checks if the given port supports mode change. Should only be called by * {@link UsbPort#isModeChangeSupported}. * * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) boolean isModeChangeSupported(UsbPort port) { try { return mService.isModeChangeSupported(port.getId()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Should only be called by {@link UsbPort#setRoles}. * * @hide */ void setPortRoles(UsbPort port, int powerRole, int dataRole) { Log.d(TAG, "setPortRoles Package:" + mContext.getPackageName()); try { mService.setPortRoles(port.getId(), powerRole, dataRole); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Enables USB port contaminant detection algorithm. * * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) void enableContaminantDetection(@NonNull UsbPort port, boolean enable) { try { mService.enableContaminantDetection(port.getId(), enable); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Should only be called by {@link UsbPort#enableLimitPowerTransfer}. *

* limits or restores power transfer in and out of USB port. * * @param port USB port for which power transfer has to be limited or restored. * @param limit limit power transfer when true. * relax power transfer restrictions when false. * @param operationId operationId for the request. * @param callback callback object to be invoked when the operation is complete. * * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) void enableLimitPowerTransfer(@NonNull UsbPort port, boolean limit, int operationId, IUsbOperationInternal callback) { Objects.requireNonNull(port, "enableLimitPowerTransfer:port must not be null. opId:" + operationId); try { mService.enableLimitPowerTransfer(port.getId(), limit, operationId, callback); } catch (RemoteException e) { Log.e(TAG, "enableLimitPowerTransfer failed. opId:" + operationId, e); try { callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException r) { Log.e(TAG, "enableLimitPowerTransfer failed to call onOperationComplete. opId:" + operationId, r); } throw e.rethrowFromSystemServer(); } } /** * Should only be called by {@link UsbPort#resetUsbPort}. *

* Disable and then re-enable USB data signaling. * * Reset USB first port.. * It will force to stop and restart USB data signaling. * Call UsbPort API if the device has more than one UsbPort. *

* * @param port reset the USB Port * @return true enable or disable USB data successfully * false if something wrong * * Should only be called by {@link UsbPort#resetUsbPort}. * * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) void resetUsbPort(@NonNull UsbPort port, int operationId, IUsbOperationInternal callback) { Objects.requireNonNull(port, "resetUsbPort: port must not be null. opId:" + operationId); try { mService.resetUsbPort(port.getId(), operationId, callback); } catch (RemoteException e) { Log.e(TAG, "resetUsbPort: failed. ", e); try { callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException r) { Log.e(TAG, "resetUsbPort: failed to call onOperationComplete. opId:" + operationId, r); } throw e.rethrowFromSystemServer(); } } /** * Should only be called by {@link UsbPort#enableUsbData}. *

* Enables or disables USB data on the specific port. * * @param port USB port for which USB data needs to be enabled or disabled. * @param enable Enable USB data when true. * Disable USB data when false. * @param operationId operationId for the request. * @param callback callback object to be invoked when the operation is complete. * @return True when the operation is asynchronous. The caller must therefore call * {@link UsbOperationInternal#waitForOperationComplete} for processing * the result. * False when the operation is synchronous. Caller can proceed reading the result * through {@link UsbOperationInternal#getStatus} * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) boolean enableUsbData(@NonNull UsbPort port, boolean enable, int operationId, IUsbOperationInternal callback) { Objects.requireNonNull(port, "enableUsbData: port must not be null. opId:" + operationId); try { return mService.enableUsbData(port.getId(), enable, operationId, callback); } catch (RemoteException e) { Log.e(TAG, "enableUsbData: failed. opId:" + operationId, e); try { callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException r) { Log.e(TAG, "enableUsbData: failed to call onOperationComplete. opId:" + operationId, r); } throw e.rethrowFromSystemServer(); } } /** * Should only be called by {@link UsbPort#enableUsbDataWhileDocked}. *

* Enables or disables USB data when disabled due to docking event. * * @param port USB port for which USB data needs to be enabled. * @param operationId operationId for the request. * @param callback callback object to be invoked when the operation is complete. * @hide */ @RequiresPermission(Manifest.permission.MANAGE_USB) void enableUsbDataWhileDocked(@NonNull UsbPort port, int operationId, IUsbOperationInternal callback) { Objects.requireNonNull(port, "enableUsbDataWhileDocked: port must not be null. opId:" + operationId); try { mService.enableUsbDataWhileDocked(port.getId(), operationId, callback); } catch (RemoteException e) { Log.e(TAG, "enableUsbDataWhileDocked: failed. opId:" + operationId, e); try { callback.onOperationComplete(UsbOperationInternal.USB_OPERATION_ERROR_INTERNAL); } catch (RemoteException r) { Log.e(TAG, "enableUsbDataWhileDocked: failed to call onOperationComplete. opId:" + operationId, r); } throw e.rethrowFromSystemServer(); } } @GuardedBy("mDisplayPortListenersLock") @RequiresPermission(Manifest.permission.MANAGE_USB) private boolean registerDisplayPortAltModeEventsIfNeededLocked() { DisplayPortAltModeInfoDispatchingListener displayPortDispatchingListener = new DisplayPortAltModeInfoDispatchingListener(); try { if (mService.registerForDisplayPortEvents(displayPortDispatchingListener)) { mDisplayPortServiceListener = displayPortDispatchingListener; return true; } return false; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Registers the given listener to listen for DisplayPort Alt Mode changes. *

* If this method returns without Exceptions, the caller should ensure to call * {@link #unregisterDisplayPortAltModeListener} when it no longer requires updates. * * @param executor Executor on which to run the listener. * @param listener DisplayPortAltModeInfoListener invoked on DisplayPortAltModeInfo * changes. See {@link #DisplayPortAltModeInfoListener} for listener * details. * * @throws IllegalStateException if listener has already been registered previously but not * unregistered or an unexpected system failure occurs. * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public void registerDisplayPortAltModeInfoListener( @NonNull @CallbackExecutor Executor executor, @NonNull DisplayPortAltModeInfoListener listener) { Objects.requireNonNull(executor, "registerDisplayPortAltModeInfoListener: " + "executor must not be null."); Objects.requireNonNull(listener, "registerDisplayPortAltModeInfoListener: " + "listener must not be null."); synchronized (mDisplayPortListenersLock) { if (mDisplayPortListeners == null) { mDisplayPortListeners = new ArrayMap(); } if (mDisplayPortServiceListener == null) { if (!registerDisplayPortAltModeEventsIfNeededLocked()) { throw new IllegalStateException("Unexpected failure registering service " + "listener"); } } if (mDisplayPortListeners.containsKey(listener)) { throw new IllegalStateException("Listener has already been registered."); } mDisplayPortListeners.put(listener, executor); } } @GuardedBy("mDisplayPortListenersLock") @RequiresPermission(Manifest.permission.MANAGE_USB) private void unregisterDisplayPortAltModeEventsLocked() { if (mDisplayPortServiceListener != null) { try { mService.unregisterForDisplayPortEvents(mDisplayPortServiceListener); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } finally { // If there was a RemoteException, the system server may have died, // and this listener probably became unregistered, so clear it for re-registration. mDisplayPortServiceListener = null; } } } /** * Unregisters the given listener if it was previously passed to * registerDisplayPortAltModeInfoListener. * * @param listener DisplayPortAltModeInfoListener used to register the listener * in registerDisplayPortAltModeInfoListener. * * @hide */ @SystemApi @RequiresPermission(Manifest.permission.MANAGE_USB) public void unregisterDisplayPortAltModeInfoListener( @NonNull DisplayPortAltModeInfoListener listener) { synchronized (mDisplayPortListenersLock) { if (mDisplayPortListeners == null) { return; } mDisplayPortListeners.remove(listener); if (mDisplayPortListeners.isEmpty()) { unregisterDisplayPortAltModeEventsLocked(); } } return; } /** * Sets the component that will handle USB device connection. *

* Setting component allows to specify external USB host manager to handle use cases, where * selection dialog for an activity that will handle USB device is undesirable. * Only system components can call this function, as it requires the MANAGE_USB permission. * * @param usbDeviceConnectionHandler The component to handle usb connections, * {@code null} to unset. * * @hide */ public void setUsbDeviceConnectionHandler(@Nullable ComponentName usbDeviceConnectionHandler) { try { mService.setUsbDeviceConnectionHandler(usbDeviceConnectionHandler); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Returns whether the given functions are valid inputs to UsbManager. * Currently the empty functions or any of MTP, PTP, RNDIS, MIDI, NCM, UVC are accepted. * * Only one function may be set at a time, except for RNDIS and NCM, which can be set together * because from a user perspective they are the same function (tethering). * * @return Whether the mask is settable. * * @hide */ public static boolean areSettableFunctions(long functions) { return functions == FUNCTION_NONE || ((~SETTABLE_FUNCTIONS & functions) == 0 && ((Long.bitCount(functions) == 1) || (functions == (FUNCTION_RNDIS | FUNCTION_NCM)))); } /** * Converts the given function mask to string. Maintains ordering with respect to init scripts. * * @return String representation of given mask * * @hide */ public static String usbFunctionsToString(long functions) { StringJoiner joiner = new StringJoiner(","); if ((functions & FUNCTION_MTP) != 0) { joiner.add(UsbManager.USB_FUNCTION_MTP); } if ((functions & FUNCTION_PTP) != 0) { joiner.add(UsbManager.USB_FUNCTION_PTP); } if ((functions & FUNCTION_RNDIS) != 0) { joiner.add(UsbManager.USB_FUNCTION_RNDIS); } if ((functions & FUNCTION_MIDI) != 0) { joiner.add(UsbManager.USB_FUNCTION_MIDI); } if ((functions & FUNCTION_ACCESSORY) != 0) { joiner.add(UsbManager.USB_FUNCTION_ACCESSORY); } if ((functions & FUNCTION_AUDIO_SOURCE) != 0) { joiner.add(UsbManager.USB_FUNCTION_AUDIO_SOURCE); } if ((functions & FUNCTION_NCM) != 0) { joiner.add(UsbManager.USB_FUNCTION_NCM); } if ((functions & FUNCTION_UVC) != 0) { joiner.add(UsbManager.USB_FUNCTION_UVC); } if ((functions & FUNCTION_ADB) != 0) { joiner.add(UsbManager.USB_FUNCTION_ADB); } return joiner.toString(); } /** * Parses a string of usb functions that are comma separated. * * @return A mask of all valid functions in the string * * @hide */ public static long usbFunctionsFromString(String functions) { if (functions == null || functions.equals(USB_FUNCTION_NONE)) { return FUNCTION_NONE; } long ret = 0; for (String function : functions.split(",")) { if (FUNCTION_NAME_TO_CODE.containsKey(function)) { ret |= FUNCTION_NAME_TO_CODE.get(function); } else if (function.length() > 0) { throw new IllegalArgumentException("Invalid usb function " + functions); } } return ret; } /** * Converts the given integer of USB speed to corresponding bandwidth. * * @return a value of USB bandwidth * * @hide */ public static int usbSpeedToBandwidth(int speed) { switch (speed) { case UsbSpeed.USB4_GEN3_40Gb: return USB_DATA_TRANSFER_RATE_40G; case UsbSpeed.USB4_GEN3_20Gb: return USB_DATA_TRANSFER_RATE_20G; case UsbSpeed.USB4_GEN2_20Gb: return USB_DATA_TRANSFER_RATE_20G; case UsbSpeed.USB4_GEN2_10Gb: return USB_DATA_TRANSFER_RATE_10G; case UsbSpeed.SUPERSPEED_20Gb: return USB_DATA_TRANSFER_RATE_20G; case UsbSpeed.SUPERSPEED_10Gb: return USB_DATA_TRANSFER_RATE_10G; case UsbSpeed.SUPERSPEED: return USB_DATA_TRANSFER_RATE_5G; case UsbSpeed.HIGHSPEED: return USB_DATA_TRANSFER_RATE_HIGH_SPEED; case UsbSpeed.FULLSPEED: return USB_DATA_TRANSFER_RATE_FULL_SPEED; case UsbSpeed.LOWSPEED: return USB_DATA_TRANSFER_RATE_LOW_SPEED; default: return USB_DATA_TRANSFER_RATE_UNKNOWN; } } /** * Converts the given usb gadgdet hal version to String * * @return String representation of Usb Gadget Hal Version * * @hide */ public static @NonNull String usbGadgetHalVersionToString(int version) { String halVersion; if (version == GADGET_HAL_V2_0) { halVersion = GADGET_HAL_VERSION_2_0; } else if (version == GADGET_HAL_V1_2) { halVersion = GADGET_HAL_VERSION_1_2; } else if (version == GADGET_HAL_V1_1) { halVersion = GADGET_HAL_VERSION_1_1; } else if (version == GADGET_HAL_V1_0) { halVersion = GADGET_HAL_VERSION_1_0; } else { halVersion = GADGET_HAL_UNKNOWN; } return halVersion; } }