Usb non-compliant port partner aidl extension

Adds aidl api definitions for notifying if the plugged Type-C
port partner (power source/accessory/cable) is non-compliant
with type-c power delivery specification. PortStatus is extended to have
a boolean that states whether or not this feature is supported as well
as an array for a new enum ComplianceWarning.

Test: atest VtsAidlUsbTargetTest
new test nonCompliantChargerStatus expects expects array to be empty
when the feature is not supported. new test nonCompliantChargerValues
expects any values in array to be in range of ComplianceWarning enums
if feature is supported.

Bug: 236322506
Change-Id: Ie3c2365e7c713327b44421c4d132b321d0e03d5f
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index e4fd65e..c6e937f 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -652,6 +652,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.usb</name>
+        <version>1-2</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ComplianceWarning.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ComplianceWarning.aidl
new file mode 100644
index 0000000..8b67070
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ComplianceWarning.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.usb;
+@Backing(type="int") @VintfStability
+enum ComplianceWarning {
+  OTHER = 1,
+  DEBUG_ACCESSORY = 2,
+  BC_1_2 = 3,
+  MISSING_RP = 4,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
index f866c1e..859f526 100644
--- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
@@ -41,5 +41,5 @@
   oneway void setCallback(in android.hardware.usb.IUsbCallback callback);
   oneway void switchRole(in String portName, in android.hardware.usb.PortRole role, long transactionId);
   oneway void limitPowerTransfer(in String portName, boolean limit, long transactionId);
-  oneway void resetUsbPort(in String portName,long transactionId);
+  oneway void resetUsbPort(in String portName, long transactionId);
 }
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
index dfd99fb..b0b7552 100644
--- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
@@ -50,4 +50,6 @@
   android.hardware.usb.UsbDataStatus[] usbDataStatus;
   boolean powerTransferLimited;
   android.hardware.usb.PowerBrickStatus powerBrickStatus;
+  boolean supportsComplianceWarnings = false;
+  android.hardware.usb.ComplianceWarning[] complianceWarnings = {};
 }
diff --git a/usb/aidl/android/hardware/usb/ComplianceWarning.aidl b/usb/aidl/android/hardware/usb/ComplianceWarning.aidl
new file mode 100644
index 0000000..4c18a31
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/ComplianceWarning.aidl
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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;
+
+@VintfStability
+@Backing(type="int")
+/**
+ * Indicates the potential non-compliance reasons for the
+ * connected USB Type-C port partner which could be a power
+ * source, accessory or cable. Applicable for USB-C receptacles
+ * in Android devices.
+ */
+enum ComplianceWarning {
+    /**
+     * Used to indicate Type-C sources/cables/accessories/ports
+     * whose issue is not listed below but do not meet
+     * specification requirements from including but not limited to
+     * USB Type-C Cable and Connector Specification, Universal Serial Bus
+     * Power Delivery Specification, and Universal Serial Bus
+     * 1.x/2.0/3.x/4.0.
+     */
+    OTHER = 1,
+    /**
+     * Used to indicate Type-C port partner
+     * (cable/accessory/source) that identifies itself as debug
+     * accessory source as defined in USB Type-C Cable and
+     * Connector Specification. However, the specification
+     * states that this is meant for debug only and shall not
+     * be used for with commercial products.
+     */
+    DEBUG_ACCESSORY = 2,
+    /**
+     * Used to indicate Type-C port partner that does not
+     * identify itself as one of the charging port types
+     * (SDP/CDP/DCP etc) as defined by Battery Charging v1.2
+     * Specification.
+     */
+    BC_1_2 = 3,
+    /**
+     * Used to indicate Type-C sources/cables that are missing
+     * pull up resistors on the CC pins as required by USB
+     * Type-C Cable and Connector Specification.
+     */
+    MISSING_RP = 4,
+}
diff --git a/usb/aidl/android/hardware/usb/PortStatus.aidl b/usb/aidl/android/hardware/usb/PortStatus.aidl
index 51bee71..d7e61ec 100644
--- a/usb/aidl/android/hardware/usb/PortStatus.aidl
+++ b/usb/aidl/android/hardware/usb/PortStatus.aidl
@@ -19,6 +19,7 @@
 import android.hardware.usb.ContaminantDetectionStatus;
 import android.hardware.usb.ContaminantProtectionMode;
 import android.hardware.usb.ContaminantProtectionStatus;
+import android.hardware.usb.ComplianceWarning;
 import android.hardware.usb.PortDataRole;
 import android.hardware.usb.PortMode;
 import android.hardware.usb.PortPowerRole;
@@ -115,4 +116,15 @@
      * Denotes whether Power brick is connected.
      */
     PowerBrickStatus powerBrickStatus;
+    /**
+     * True if the hal implementation can support identifying
+     * non compliant USB power source/cable/accessory. False other
+     * otherwise.
+     */
+    boolean supportsComplianceWarnings = false;
+    /**
+     * List of reasons as to why the attached USB
+     * power source/cable/accessory is non compliant.
+     */
+    ComplianceWarning[] complianceWarnings = {};
 }
diff --git a/usb/aidl/default/Android.bp b/usb/aidl/default/Android.bp
index 7cb2822..2e2c3d9 100644
--- a/usb/aidl/default/Android.bp
+++ b/usb/aidl/default/Android.bp
@@ -34,10 +34,10 @@
         "Usb.cpp",
     ],
     shared_libs: [
-        "android.hardware.usb-V1-ndk",
+        "android.hardware.usb-V2-ndk",
         "libbase",
         "libbinder_ndk",
-	"libcutils",
+        "libcutils",
         "liblog",
         "libutils",
     ],
diff --git a/usb/aidl/default/Usb.cpp b/usb/aidl/default/Usb.cpp
index 7e738c4..dd12da0 100644
--- a/usb/aidl/default/Usb.cpp
+++ b/usb/aidl/default/Usb.cpp
@@ -123,6 +123,15 @@
     return Status::SUCCESS;
 }
 
+Status queryNonCompliantChargerStatus(std::vector<PortStatus> *currentPortStatus) {
+    string reasons, path;
+
+    for (int i = 0; i < currentPortStatus->size(); i++) {
+        (*currentPortStatus)[i].supportsComplianceWarnings = false;
+    }
+    return Status::SUCCESS;
+}
+
 string appendRoleNodeHelper(const string &portName, PortRole::Tag tag) {
     string node(kTypecPath + portName);
 
@@ -527,6 +536,7 @@
     pthread_mutex_lock(&usb->mLock);
     status = getPortStatusHelper(currentPortStatus);
     queryMoistureDetectionStatus(currentPortStatus);
+    queryNonCompliantChargerStatus(currentPortStatus);
     if (usb->mCallback != NULL) {
         ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus,
             status);
diff --git a/usb/aidl/default/android.hardware.usb-service.example.xml b/usb/aidl/default/android.hardware.usb-service.example.xml
index 6088194..c3f07f5 100644
--- a/usb/aidl/default/android.hardware.usb-service.example.xml
+++ b/usb/aidl/default/android.hardware.usb-service.example.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.usb</name>
-        <version>1</version>
+        <version>2</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
diff --git a/usb/aidl/vts/Android.bp b/usb/aidl/vts/Android.bp
index 00a7c93..d0e0eec 100644
--- a/usb/aidl/vts/Android.bp
+++ b/usb/aidl/vts/Android.bp
@@ -34,7 +34,7 @@
         "libbinder_ndk",
     ],
     static_libs: [
-        "android.hardware.usb-V1-ndk",
+        "android.hardware.usb-V2-ndk",
     ],
     test_suites: [
         "general-tests",
diff --git a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
index ea2f985..c4ec8a4 100644
--- a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
+++ b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
@@ -43,6 +43,7 @@
 #define TIMEOUT_PERIOD 10
 
 using ::aidl::android::hardware::usb::BnUsbCallback;
+using ::aidl::android::hardware::usb::ComplianceWarning;
 using ::aidl::android::hardware::usb::IUsb;
 using ::aidl::android::hardware::usb::IUsbCallback;
 using ::aidl::android::hardware::usb::PortDataRole;
@@ -560,6 +561,53 @@
   ALOGI("UsbAidlTest resetUsbPort end");
 }
 
+/*
+ * Test charger compliance warning
+ * The test asserts that complianceWarnings is
+ * empty when the feature is not supported. i.e.
+ * supportsComplianceWarning is false.
+ */
+TEST_P(UsbAidlTest, nonCompliantChargerStatus) {
+    ALOGI("UsbAidlTest nonCompliantChargerStatus start");
+    int64_t transactionId = rand() % 10000;
+    const auto& ret = usb->queryPortStatus(transactionId);
+    ASSERT_TRUE(ret.isOk());
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(2, usb_last_cookie);
+    EXPECT_EQ(transactionId, last_transactionId);
+
+    if (!usb_last_port_status.supportsComplianceWarnings) {
+      EXPECT_TRUE(usb_last_port_status.complianceWarnings.empty());
+    }
+
+    ALOGI("UsbAidlTest nonCompliantChargerStatus end");
+}
+
+/*
+ * Test charger compliance warning values
+ * The test asserts that complianceWarning values
+ * are valid.
+ */
+TEST_P(UsbAidlTest, nonCompliantChargerValues) {
+    ALOGI("UsbAidlTest nonCompliantChargerValues start");
+    int64_t transactionId = rand() % 10000;
+    const auto& ret = usb->queryPortStatus(transactionId);
+    ASSERT_TRUE(ret.isOk());
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(2, usb_last_cookie);
+    EXPECT_EQ(transactionId, last_transactionId);
+
+    // Current compliance values range from [1, 4]
+    if (usb_last_port_status.supportsComplianceWarnings) {
+      for (auto warning : usb_last_port_status.complianceWarnings) {
+        EXPECT_TRUE((int)warning >= (int)ComplianceWarning::OTHER);
+        EXPECT_TRUE((int)warning <= (int)ComplianceWarning::MISSING_RP);
+      }
+    }
+
+    ALOGI("UsbAidlTest nonCompliantChargerValues end");
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest);
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, UsbAidlTest,