| /* |
| * 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. |
| * |
| * <div class="special reference"> |
| * <h3>Developer Guides</h3> |
| * <p>For more information about communicating with USB hardware, read the |
| * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p> |
| * </div> |
| */ |
| @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, |
| * <ul> |
| * <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected. |
| * <li> {@link #USB_HOST_CONNECTED} boolean indicating whether USB is connected or |
| * disconnected as host. |
| * <li> {@link #USB_CONFIGURED} boolean indicating whether USB is configured. |
| * currently zero if not configured, one for configured. |
| * <li> {@link #USB_FUNCTION_ADB} boolean extra indicating whether the |
| * adb function is enabled |
| * <li> {@link #USB_FUNCTION_RNDIS} boolean extra indicating whether the |
| * RNDIS ethernet function is enabled |
| * <li> {@link #USB_FUNCTION_MTP} boolean extra indicating whether the |
| * MTP function is enabled |
| * <li> {@link #USB_FUNCTION_PTP} boolean extra indicating whether the |
| * PTP function is enabled |
| * <li> {@link #USB_FUNCTION_ACCESSORY} boolean extra indicating whether the |
| * accessory function is enabled |
| * <li> {@link #USB_FUNCTION_AUDIO_SOURCE} boolean extra indicating whether the |
| * audio source function is enabled |
| * <li> {@link #USB_FUNCTION_MIDI} boolean extra indicating whether the |
| * MIDI function is enabled |
| * <li> {@link #USB_FUNCTION_UVC} boolean extra indicating whether the |
| * UVC function is enabled |
| * </ul> |
| * 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. |
| * <ul> |
| * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice} |
| * for the attached device |
| * </ul> |
| */ |
| @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. |
| * <ul> |
| * <li> {@link #EXTRA_DEVICE} containing the {@link android.hardware.usb.UsbDevice} |
| * for the detached device |
| * </ul> |
| */ |
| @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. |
| * |
| * <ul> |
| * <li> {@link #EXTRA_ACCESSORY} containing the {@link android.hardware.usb.UsbAccessory} |
| * for the attached accessory |
| * </ul> |
| */ |
| @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. |
| * <ul> |
| * <li> {@link #EXTRA_ACCESSORY} containing the {@link UsbAccessory} |
| * for the attached accessory that was detached |
| * </ul> |
| */ |
| @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 |
| * |
| * <p>For more information about communicating with USB accessory handshake, refer to |
| * <a href="https://source.android.com/devices/accessories/aoa">AOA</a> developer guide.</p> |
| * |
| * @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 |
| * |
| * <p>For more information about control request with identifying string information |
| * between communicating with USB accessory handshake, refer to |
| * <a href="https://source.android.com/devices/accessories/aoa">AOA</a> developer guide.</p> |
| * |
| * @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<String, Long> 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<DisplayPortAltModeInfoListener, Executor> 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<DisplayPortAltModeInfoListener, Executor> 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<String,UsbDevice> getDeviceList() { |
| HashMap<String,UsbDevice> result = new HashMap<String,UsbDevice>(); |
| 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. |
| * |
| * <p>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. |
| * |
| * <p>Not for third-party apps.</p> |
| * |
| * @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. |
| * |
| * <p>Not for third-party apps.</p> |
| * |
| * @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: |
| * <ul> |
| * <li> {@link #EXTRA_DEVICE} containing the device passed into this call |
| * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether |
| * permission was granted by the user |
| * </ul> |
| * |
| * 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: |
| * <ul> |
| * <li> {@link #EXTRA_ACCESSORY} containing the accessory passed into this call |
| * <li> {@link #EXTRA_PERMISSION_GRANTED} containing boolean indicating whether |
| * permission was granted by the user |
| * </ul> |
| * |
| * @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. |
| * <p> |
| * USB functions represent interfaces which are published to the host to access |
| * services offered by the device. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * USB functions represent interfaces which are published to the host to access |
| * services offered by the device. |
| * </p><p> |
| * 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. |
| * </p><p> |
| * An argument of 0 indicates that the device is charging, and can pick any |
| * appropriate function for that purpose. |
| * </p><p> |
| * Note: This function is asynchronous and may fail silently without applying |
| * the requested changes. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * This function returns the state of primary USB functions and can return a |
| * mask containing any usb function(s) except for ADB. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * A zero mask has the effect of switching off this feature, so functions |
| * no longer change on screen unlock. |
| * </p><p> |
| * 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. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * This function returns the current Gadget Hal Version. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * This function returns the current USB Hal Version. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * Performs USB data stack reset through USB Gadget HAL. |
| * It will force USB data connection reset. The connection will disconnect and reconnect. |
| * </p> |
| * |
| * @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. |
| * <p> |
| * Enables/Disables USB data path of all USB ports. |
| * It will force to stop or restore USB data signaling. |
| * </p> |
| * |
| * @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<UsbPort> usbPorts, boolean disable, |
| boolean revertOnFailure) { |
| List<UsbPort> 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. |
| * <p> |
| * 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). |
| * </p> |
| * |
| * @return The list of USB ports |
| * |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.MANAGE_USB) |
| public @NonNull List<UsbPort> getPorts() { |
| if (mService == null) { |
| return Collections.emptyList(); |
| } |
| |
| List<ParcelableUsbPort> parcelablePorts; |
| try { |
| parcelablePorts = mService.getPorts(); |
| } catch (RemoteException e) { |
| throw e.rethrowFromSystemServer(); |
| } |
| |
| if (parcelablePorts == null) { |
| return Collections.emptyList(); |
| } else { |
| int numPorts = parcelablePorts.size(); |
| |
| ArrayList<UsbPort> 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}. |
| * <p> |
| * 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}. |
| * <p> |
| * 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. |
| * </p> |
| * |
| * @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}. |
| * <p> |
| * 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}. |
| * <p> |
| * 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. |
| * <p> |
| * 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<DisplayPortAltModeInfoListener, |
| Executor>(); |
| } |
| |
| 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. |
| * <p> |
| * 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; |
| } |
| } |