Extend USB compliance warning API

Add USB feature flags and guard the new compliance warning APIs.

Test: atest VtsAidlUsbTargetTest
      atest CtsUsbManagerTestCases
Bug: 296119135
Bug: 300340959
Change-Id: Iffca537a85cb03ab5eeb2ad331a145ef1d2b848a
diff --git a/AconfigFlags.bp b/AconfigFlags.bp
index ab0d5a3..3a772e1 100644
--- a/AconfigFlags.bp
+++ b/AconfigFlags.bp
@@ -61,6 +61,7 @@
     ":service-jobscheduler-deviceidle.flags-aconfig-java{.generated_srcjars}",
     ":surfaceflinger_flags_java_lib{.generated_srcjars}",
     ":android.view.contentcapture.flags-aconfig-java{.generated_srcjars}",
+    ":android.hardware.usb.flags-aconfig-java{.generated_srcjars}",
 ]
 
 filegroup {
@@ -681,3 +682,16 @@
     aconfig_declarations: "android.view.contentcapture.flags-aconfig",
     defaults: ["framework-minus-apex-aconfig-java-defaults"],
 }
+
+// USB
+aconfig_declarations {
+    name: "android.hardware.usb.flags-aconfig",
+    package: "android.hardware.usb.flags",
+    srcs: ["core/java/android/hardware/usb/flags/*.aconfig"],
+}
+
+java_aconfig_library {
+    name: "android.hardware.usb.flags-aconfig-java",
+    aconfig_declarations: "android.hardware.usb.flags-aconfig",
+    defaults: ["framework-minus-apex-aconfig-java-defaults"],
+}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 2a3593b..8bebd6b 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -6188,8 +6188,13 @@
     method public void writeToParcel(android.os.Parcel, int);
     field public static final int COMPLIANCE_WARNING_BC_1_2 = 3; // 0x3
     field public static final int COMPLIANCE_WARNING_DEBUG_ACCESSORY = 2; // 0x2
+    field @FlaggedApi("android.hardware.usb.flags.enable_usb_data_compliance_warning") public static final int COMPLIANCE_WARNING_ENUMERATION_FAIL = 7; // 0x7
+    field @FlaggedApi("android.hardware.usb.flags.enable_usb_data_compliance_warning") public static final int COMPLIANCE_WARNING_FLAKY_CONNECTION = 8; // 0x8
+    field @FlaggedApi("android.hardware.usb.flags.enable_usb_data_compliance_warning") public static final int COMPLIANCE_WARNING_INPUT_POWER_LIMITED = 5; // 0x5
+    field @FlaggedApi("android.hardware.usb.flags.enable_usb_data_compliance_warning") public static final int COMPLIANCE_WARNING_MISSING_DATA_LINES = 6; // 0x6
     field public static final int COMPLIANCE_WARNING_MISSING_RP = 4; // 0x4
     field public static final int COMPLIANCE_WARNING_OTHER = 1; // 0x1
+    field @FlaggedApi("android.hardware.usb.flags.enable_usb_data_compliance_warning") public static final int COMPLIANCE_WARNING_UNRELIABLE_IO = 9; // 0x9
     field @NonNull public static final android.os.Parcelable.Creator<android.hardware.usb.UsbPortStatus> CREATOR;
     field public static final int DATA_ROLE_DEVICE = 2; // 0x2
     field public static final int DATA_ROLE_HOST = 1; // 0x1
diff --git a/core/java/android/hardware/usb/UsbPort.java b/core/java/android/hardware/usb/UsbPort.java
index 490b128..8f0149b 100644
--- a/core/java/android/hardware/usb/UsbPort.java
+++ b/core/java/android/hardware/usb/UsbPort.java
@@ -52,6 +52,11 @@
 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_BC_1_2;
 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP;
 import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_OTHER;
+import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED;
+import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES;
+import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL;
+import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION;
+import static android.hardware.usb.UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO;
 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_UNKNOWN;
 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_NOT_CAPABLE;
 import static android.hardware.usb.DisplayPortAltModeInfo.DISPLAYPORT_ALT_MODE_STATUS_CAPABLE_DISABLED;
@@ -789,6 +794,21 @@
                     case UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP:
                         complianceWarningString.append("missing rp, ");
                         break;
+                    case UsbPortStatus.COMPLIANCE_WARNING_INPUT_POWER_LIMITED:
+                        complianceWarningString.append("input power limited, ");
+                        break;
+                    case UsbPortStatus.COMPLIANCE_WARNING_MISSING_DATA_LINES:
+                        complianceWarningString.append("missing data lines, ");
+                        break;
+                    case UsbPortStatus.COMPLIANCE_WARNING_ENUMERATION_FAIL:
+                        complianceWarningString.append("enumeration fail, ");
+                        break;
+                    case UsbPortStatus.COMPLIANCE_WARNING_FLAKY_CONNECTION:
+                        complianceWarningString.append("flaky connection, ");
+                        break;
+                    case UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO:
+                        complianceWarningString.append("unreliable io, ");
+                        break;
                     default:
                         complianceWarningString.append(String.format("Unknown(%d), ", warning));
                         break;
diff --git a/core/java/android/hardware/usb/UsbPortStatus.java b/core/java/android/hardware/usb/UsbPortStatus.java
index b4fe3a2..d959240 100644
--- a/core/java/android/hardware/usb/UsbPortStatus.java
+++ b/core/java/android/hardware/usb/UsbPortStatus.java
@@ -18,11 +18,13 @@
 
 import android.Manifest;
 import android.annotation.CheckResult;
+import android.annotation.FlaggedApi;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.hardware.usb.flags.Flags;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -310,6 +312,54 @@
     public static final int COMPLIANCE_WARNING_MISSING_RP = 4;
 
     /**
+     * Used to indicate the charging setups on the USB ports are unable to
+     * deliver negotiated power. Introduced in Android V (API level 35)
+     * and client applicantions that target API levels lower than 35 will
+     * receive {@link #COMPLIANCE_WARNING_OTHER} instead.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING)
+    public static final int COMPLIANCE_WARNING_INPUT_POWER_LIMITED = 5;
+
+    /**
+     * Used to indicate the cable/connector on the USB ports are missing
+     * the required wires on the data pins to make data transfer.
+     * Introduced in Android V (API level 35) and client applicantions that
+     * target API levels lower than 35 will receive
+     * {@link #COMPLIANCE_WARNING_OTHER} instead.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING)
+    public static final int COMPLIANCE_WARNING_MISSING_DATA_LINES = 6;
+
+    /**
+     * Used to indicate enumeration failures on the USB ports, potentially due to
+     * signal integrity issues or other causes. Introduced in Android V
+     * (API level 35) and client applicantions that target API levels lower
+     * than 35 will receive {@link #COMPLIANCE_WARNING_OTHER} instead.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING)
+    public static final int COMPLIANCE_WARNING_ENUMERATION_FAIL = 7;
+
+    /**
+     * Used to indicate unexpected data disconnection on the USB ports,
+     * potentially due to signal integrity issues or other causes.
+     * Introduced in Android V (API level 35) and client applicantions that
+     * target API levels lower than 35 will receive
+     * {@link #COMPLIANCE_WARNING_OTHER} instead.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING)
+    public static final int COMPLIANCE_WARNING_FLAKY_CONNECTION = 8;
+
+    /**
+     * Used to indicate unreliable or slow data transfer on the USB ports,
+     * potentially due to signal integrity issues or other causes.
+     * Introduced in Android V (API level 35) and client applicantions that
+     * target API levels lower than 35 will receive
+     * {@link #COMPLIANCE_WARNING_OTHER} instead.
+     */
+    @FlaggedApi(Flags.FLAG_ENABLE_USB_DATA_COMPLIANCE_WARNING)
+    public static final int COMPLIANCE_WARNING_UNRELIABLE_IO = 9;
+
+    /**
      * Indicates that the Type-C plug orientation cannot be
      * determined because the connected state of the device is unknown.
      */
@@ -372,6 +422,11 @@
             COMPLIANCE_WARNING_DEBUG_ACCESSORY,
             COMPLIANCE_WARNING_BC_1_2,
             COMPLIANCE_WARNING_MISSING_RP,
+            COMPLIANCE_WARNING_INPUT_POWER_LIMITED,
+            COMPLIANCE_WARNING_MISSING_DATA_LINES,
+            COMPLIANCE_WARNING_ENUMERATION_FAIL,
+            COMPLIANCE_WARNING_FLAKY_CONNECTION,
+            COMPLIANCE_WARNING_UNRELIABLE_IO,
     })
     @Retention(RetentionPolicy.SOURCE)
     @interface ComplianceWarning{}
@@ -591,7 +646,12 @@
      * @return array including {@link #COMPLIANCE_WARNING_OTHER},
      *         {@link #COMPLIANCE_WARNING_DEBUG_ACCESSORY},
      *         {@link #COMPLIANCE_WARNING_BC_1_2},
-     *         or {@link #COMPLIANCE_WARNING_MISSING_RP}
+     *         {@link #COMPLIANCE_WARNING_MISSING_RP},
+     *         {@link #COMPLIANCE_WARNING_INPUT_POWER_LIMITED},
+     *         {@link #COMPLIANCE_WARNING_MISSING_DATA_LINES},
+     *         {@link #COMPLIANCE_WARNING_ENUMERATION_FAIL},
+     *         {@link #COMPLIANCE_WARNING_FLAKY_CONNECTION},
+     *         {@link #COMPLIANCE_WARNING_UNRELIABLE_IO}.
      */
     @CheckResult
     @NonNull
diff --git a/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
new file mode 100644
index 0000000..6b78d05
--- /dev/null
+++ b/core/java/android/hardware/usb/flags/system_sw_usb_flags.aconfig
@@ -0,0 +1,8 @@
+package: "android.hardware.usb.flags"
+
+flag {
+    name: "enable_usb_data_compliance_warning"
+    namespace: "system_sw_usb"
+    description: "Enable USB data compliance warnings when set"
+    bug: "296119135"
+}
diff --git a/services/usb/Android.bp b/services/usb/Android.bp
index 9f3b52e..1dc5dcf 100644
--- a/services/usb/Android.bp
+++ b/services/usb/Android.bp
@@ -33,6 +33,6 @@
         "android.hardware.usb-V1.1-java",
         "android.hardware.usb-V1.2-java",
         "android.hardware.usb-V1.3-java",
-        "android.hardware.usb-V2-java",
+        "android.hardware.usb-V3-java",
     ],
 }
diff --git a/services/usb/java/com/android/server/usb/UsbService.java b/services/usb/java/com/android/server/usb/UsbService.java
index 35e2fcf..fb13b33 100644
--- a/services/usb/java/com/android/server/usb/UsbService.java
+++ b/services/usb/java/com/android/server/usb/UsbService.java
@@ -1285,12 +1285,17 @@
                 pw.println("  dumpsys usb add-port \"matrix\" dual --compliance-warnings");
                 pw.println("  dumpsys usb set-compliance-reasons \"matrix\" <reason-list>");
                 pw.println("  dumpsys usb clear-compliance-reasons \"matrix\"");
-                pw.println("<reason-list> is expected to be formatted as \"1, ..., 4\"");
+                pw.println("<reason-list> is expected to be formatted as \"1, ..., N\"");
                 pw.println("with reasons that need to be simulated.");
                 pw.println("  1: other");
                 pw.println("  2: debug accessory");
                 pw.println("  3: bc12");
                 pw.println("  4: missing rp");
+                pw.println("  5: input power limited");
+                pw.println("  6: missing data lines");
+                pw.println("  7: enumeration fail");
+                pw.println("  8: flaky connection");
+                pw.println("  9: unreliable io");
                 pw.println();
                 pw.println("Example simulate DisplayPort Alt Mode Changes:");
                 pw.println("  dumpsys usb add-port \"matrix\" dual --displayport");
diff --git a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
index c7a7a9b..45b623b 100644
--- a/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
+++ b/services/usb/java/com/android/server/usb/hal/port/UsbPortAidl.java
@@ -39,6 +39,7 @@
 import android.hardware.usb.AltModeData;
 import android.hardware.usb.AltModeData.DisplayPortAltModeData;
 import android.hardware.usb.DisplayPortAltModePinAssignment;
+import android.hardware.usb.flags.Flags;
 import android.os.Build;
 import android.os.ServiceManager;
 import android.os.IBinder;
@@ -593,11 +594,21 @@
             for (int warning : complianceWarnings) {
                 if (newComplianceWarnings.indexOf(warning) == -1
                         && warning >= UsbPortStatus.COMPLIANCE_WARNING_OTHER) {
-                    // ComplianceWarnings range from [1, 4] in Android U
-                    if (warning > UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP) {
-                        newComplianceWarnings.add(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+                    if (Flags.enableUsbDataComplianceWarning()) {
+                        // ComplianceWarnings range extends to [1, 9] when feature flag is on
+                        if (warning
+                                > UsbPortStatus.COMPLIANCE_WARNING_UNRELIABLE_IO) {
+                            newComplianceWarnings.add(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+                        } else {
+                            newComplianceWarnings.add(warning);
+                        }
                     } else {
-                        newComplianceWarnings.add(warning);
+                        // ComplianceWarnings range from [1, 4] in Android U
+                        if (warning > UsbPortStatus.COMPLIANCE_WARNING_MISSING_RP) {
+                            newComplianceWarnings.add(UsbPortStatus.COMPLIANCE_WARNING_OTHER);
+                        } else {
+                            newComplianceWarnings.add(warning);
+                        }
                     }
                 }
             }