diff --git a/api/system-current.txt b/api/system-current.txt index e532a3afab8a9..7df4229c24c86 100755 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -3622,6 +3622,7 @@ package android.hardware.usb { method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions(); method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List getPorts(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void grantPermission(android.hardware.usb.UsbDevice, String); + method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void resetUsbGadget(); method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long); field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED"; field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE"; diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl index c8dbd16005acb..e32865ebeced2 100644 --- a/core/java/android/hardware/usb/IUsbManager.aidl +++ b/core/java/android/hardware/usb/IUsbManager.aidl @@ -126,6 +126,9 @@ interface IUsbManager /* Gets the current screen unlocked functions. */ long getScreenUnlockedFunctions(); + /* Resets the USB gadget. */ + void resetUsbGadget(); + /* Get the functionfs control handle for the given function. Usb * descriptors will already be written, and the handle will be * ready to use. diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java index 67fdda37ed3b0..827353b1802c5 100644 --- a/core/java/android/hardware/usb/UsbManager.java +++ b/core/java/android/hardware/usb/UsbManager.java @@ -793,6 +793,25 @@ public class UsbManager { } } + /** + * 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 a list of physical USB ports on the device. *

diff --git a/services/usb/Android.bp b/services/usb/Android.bp index d2c973abbc746..a9474c10017ea 100644 --- a/services/usb/Android.bp +++ b/services/usb/Android.bp @@ -19,5 +19,6 @@ java_library_static { "android.hardware.usb-V1.1-java", "android.hardware.usb-V1.2-java", "android.hardware.usb.gadget-V1.0-java", + "android.hardware.usb.gadget-V1.1-java", ], } diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java index 9f3b07b951bea..6407ec76958ec 100644 --- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java +++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java @@ -161,6 +161,7 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser private static final int MSG_GET_CURRENT_USB_FUNCTIONS = 16; private static final int MSG_FUNCTION_SWITCH_TIMEOUT = 17; private static final int MSG_GADGET_HAL_REGISTERED = 18; + private static final int MSG_RESET_USB_GADGET = 19; private static final int AUDIO_MODE_SOURCE = 1; @@ -1846,6 +1847,23 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser } } break; + case MSG_RESET_USB_GADGET: + synchronized (mGadgetProxyLock) { + if (mGadgetProxy == null) { + Slog.e(TAG, "reset Usb Gadget mGadgetProxy is null"); + break; + } + + try { + android.hardware.usb.gadget.V1_1.IUsbGadget gadgetProxy = + android.hardware.usb.gadget.V1_1.IUsbGadget + .castFrom(mGadgetProxy); + gadgetProxy.reset(); + } catch (RemoteException e) { + Slog.e(TAG, "reset Usb Gadget failed", e); + } + } + break; default: super.handleMessage(msg); } @@ -2054,6 +2072,17 @@ public class UsbDeviceManager implements ActivityTaskManagerInternal.ScreenObser mHandler.sendMessage(MSG_SET_SCREEN_UNLOCKED_FUNCTIONS, functions); } + /** + * Resets the USB Gadget. + */ + public void resetUsbGadget() { + if (DEBUG) { + Slog.d(TAG, "reset Usb Gadget"); + } + + mHandler.sendMessage(MSG_RESET_USB_GADGET, null); + } + private void onAdbEnabled(boolean enabled) { mHandler.sendMessage(MSG_ENABLE_ADB, enabled); } diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java index 275319491e398..c615b3d67e01a 100644 --- a/services/usb/java/com/android/server/usb/UsbService.java +++ b/services/usb/java/com/android/server/usb/UsbService.java @@ -621,6 +621,19 @@ public class UsbService extends IUsbManager.Stub { return mDeviceManager.getScreenUnlockedFunctions(); } + @Override + public void resetUsbGadget() { + mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null); + Preconditions.checkNotNull(mDeviceManager, "DeviceManager must not be null"); + + final long ident = Binder.clearCallingIdentity(); + try { + mDeviceManager.resetUsbGadget(); + } finally { + Binder.restoreCallingIdentity(ident); + } + } + @Override public List getPorts() { mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);