aidl: usb: Support contaminant presence detection

Change-Id: Ia2e704874a8ed336f97ca756b0ea26cdc40aa5d3
diff --git a/aidl/usb/Usb.cpp b/aidl/usb/Usb.cpp
index 71d792e..d39d7ca 100644
--- a/aidl/usb/Usb.cpp
+++ b/aidl/usb/Usb.cpp
@@ -54,6 +54,30 @@
 // Set by the signal handler to destroy the thread
 volatile bool destroyThread;
 
+int32_t readFile(const std::string &filename, std::string *contents) {
+    FILE *fp;
+    ssize_t read = 0;
+    char *line = NULL;
+    size_t len = 0;
+
+    fp = fopen(filename.c_str(), "r");
+    if (fp != NULL) {
+        if ((read = getline(&line, &len, fp)) != -1) {
+            char *pos;
+            if ((pos = strchr(line, '\n')) != NULL)
+                *pos = '\0';
+            *contents = line;
+        }
+        free(line);
+        fclose(fp);
+        return 0;
+    } else {
+        ALOGE("fopen failed");
+    }
+
+    return -1;
+}
+
 void queryVersionHelper(android::hardware::usb::Usb *usb,
                         std::vector<PortStatus> *currentPortStatus);
 
@@ -113,7 +137,8 @@
     return ScopedAStatus::ok();
 }
 
-Status queryMoistureDetectionStatus(std::vector<PortStatus> *currentPortStatus) {
+Status queryMoistureDetectionStatus(android::hardware::usb::Usb *usb,
+                                    std::vector<PortStatus> *currentPortStatus) {
     string enabled, status, path, DetectedPath;
 
     for (int i = 0; i < currentPortStatus->size(); i++) {
@@ -122,9 +147,28 @@
         (*currentPortStatus)[i].contaminantProtectionStatus
                 = ContaminantProtectionStatus::NONE;
         (*currentPortStatus)[i].contaminantDetectionStatus
-                = ContaminantDetectionStatus::NOT_SUPPORTED;
-        (*currentPortStatus)[i].supportsEnableContaminantPresenceDetection = false;
+                = ContaminantDetectionStatus::DISABLED;
+        (*currentPortStatus)[i].supportsEnableContaminantPresenceDetection = true;
         (*currentPortStatus)[i].supportsEnableContaminantPresenceProtection = false;
+
+        if (usb->mMoistureDetectionEnabled) {
+            if (readFile(CONTAMINANT_DETECTION_PATH, &status)) {
+                ALOGE("Failed to open %s", CONTAMINANT_DETECTION_PATH);
+                return Status::ERROR;
+            }
+            if (status == "1") {
+                (*currentPortStatus)[i].contaminantDetectionStatus =
+                    ContaminantDetectionStatus::DETECTED;
+                (*currentPortStatus)[i].contaminantProtectionStatus =
+                    ContaminantProtectionStatus::FORCE_SINK;
+            } else
+                (*currentPortStatus)[i].contaminantDetectionStatus =
+                    ContaminantDetectionStatus::NOT_DETECTED;
+        }
+
+        ALOGI("ContaminantDetectionStatus[%d]:%hhd ContaminantProtectionStatus[%d]:%hhd",
+              i, (*currentPortStatus)[i].contaminantDetectionStatus,
+              i, (*currentPortStatus)[i].contaminantProtectionStatus);
     }
 
     return Status::SUCCESS;
@@ -252,7 +296,8 @@
     : mLock(PTHREAD_MUTEX_INITIALIZER),
       mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
       mPartnerLock(PTHREAD_MUTEX_INITIALIZER),
-      mPartnerUp(false)
+      mPartnerUp(false),
+      mMoistureDetectionEnabled(false)
 {
     pthread_condattr_t attr;
     if (pthread_condattr_init(&attr)) {
@@ -533,7 +578,7 @@
     Status status;
     pthread_mutex_lock(&usb->mLock);
     status = getPortStatusHelper(currentPortStatus);
-    queryMoistureDetectionStatus(currentPortStatus);
+    queryMoistureDetectionStatus(usb, currentPortStatus);
     if (usb->mCallback != NULL) {
         ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus,
             status);
@@ -564,13 +609,17 @@
 }
 
 ScopedAStatus Usb::enableContaminantPresenceDetection(const string& in_portName,
-        bool /*in_enable*/, int64_t in_transactionId) {
+        bool in_enable, int64_t in_transactionId) {
     std::vector<PortStatus> currentPortStatus;
+    std::string disable = GetProperty(DISABLE_CONTAMINANT_DETECTION, "");
+
+    if (disable != "true")
+        mMoistureDetectionEnabled = in_enable;
 
     pthread_mutex_lock(&mLock);
     if (mCallback != NULL) {
         ScopedAStatus ret = mCallback->notifyContaminantEnabledStatus(
-            in_portName, false, Status::ERROR, in_transactionId);
+            in_portName, false, Status::SUCCESS, in_transactionId);
         if (!ret.isOk())
             ALOGE("enableContaminantPresenceDetection  error %s", ret.getDescription().c_str());
     } else {
@@ -610,7 +659,9 @@
             payload->usb->mPartnerUp = true;
             pthread_cond_signal(&payload->usb->mPartnerCV);
             pthread_mutex_unlock(&payload->usb->mPartnerLock);
-        } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_"))) {
+        } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_")) ||
+                   !strncmp(cp, "CCIC=WATER", strlen("CCIC=WATER")) ||
+                   !strncmp(cp, "CCIC=DRY", strlen("CCIC=DRY"))) {
             std::vector<PortStatus> currentPortStatus;
             queryVersionHelper(payload->usb, &currentPortStatus);
 
diff --git a/aidl/usb/Usb.h b/aidl/usb/Usb.h
index 46be609..a0794f3 100644
--- a/aidl/usb/Usb.h
+++ b/aidl/usb/Usb.h
@@ -30,6 +30,8 @@
 // structures created and uvent fired.
 #define PORT_TYPE_TIMEOUT 8
 #define USB_DATA_PATH "/sys/devices/virtual/usb_notify/usb_control/usb_data_enabled"
+#define CONTAMINANT_DETECTION_PATH "/sys/devices/virtual/sec/ccic/water"
+#define DISABLE_CONTAMINANT_DETECTION "vendor.usb.contaminantdisable"
 
 namespace aidl {
 namespace android {
@@ -74,6 +76,7 @@
     pthread_mutex_t mPartnerLock;
     // Variable to signal partner coming back online after type switch
     bool mPartnerUp;
+    bool mMoistureDetectionEnabled;
   private:
     pthread_t mPoll;
 };