Merge changes from topic "usb_gadget_reset"

* changes:
  Add svc usb resetUsbGadget method
  Support USB Gadget V1.1 HAL
diff --git a/api/system-current.txt b/api/system-current.txt
index 7247fe4..31e1699 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3686,6 +3686,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public long getCurrentFunctions();
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USB) public java.util.List<android.hardware.usb.UsbPort> 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/cmds/svc/src/com/android/commands/svc/UsbCommand.java b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
index 3893be4..cd751f4 100644
--- a/cmds/svc/src/com/android/commands/svc/UsbCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/UsbCommand.java
@@ -42,7 +42,9 @@
                 + "         Sets the functions which, if the device was charging, become current on"
                     + "screen unlock. If function is blank, turn off this feature.\n"
                 + "       svc usb getFunctions\n"
-                + "          Gets the list of currently enabled functions\n\n"
+                + "          Gets the list of currently enabled functions\n"
+                + "       svc usb resetUsbGadget\n"
+                + "          Reset usb gadget\n\n"
                 + "possible values of [function] are any of 'mtp', 'ptp', 'rndis', 'midi'\n";
     }
 
@@ -75,6 +77,13 @@
                     System.err.println("Error communicating with UsbManager: " + e);
                 }
                 return;
+            } else if ("resetUsbGadget".equals(args[1])) {
+                try {
+                    usbMgr.resetUsbGadget();
+                } catch (RemoteException e) {
+                    System.err.println("Error communicating with UsbManager: " + e);
+                }
+                return;
             }
         }
         System.err.println(longHelp());
diff --git a/core/java/android/hardware/usb/IUsbManager.aidl b/core/java/android/hardware/usb/IUsbManager.aidl
index c8dbd16..e32865e 100644
--- a/core/java/android/hardware/usb/IUsbManager.aidl
+++ b/core/java/android/hardware/usb/IUsbManager.aidl
@@ -126,6 +126,9 @@
     /* 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 67fdda3..827353b 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -794,6 +794,25 @@
     }
 
     /**
+     * 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 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
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index d2c973a..a9474c1 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -19,5 +19,6 @@
         "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 9f3b07b..6407ec7 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 @@
     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 @@
                         }
                     }
                     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 @@
         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 0a03f14..61f2c50 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -638,6 +638,19 @@
     }
 
     @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<ParcelableUsbPort> getPorts() {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USB, null);