gs101: usb: Report USB port overheat event

Read duration stats expoted by google,usbc_port_cooling_dev and
push suez atom when the uevent is received. The plugged temperature
is queried every time when the USB port is connected. Maximum
temperature during overheat is queried when the uevent is received.

Bug: 193615568
Change-Id: Ib02e14dbdbe1390476e864d351158c1523a5c311
diff --git a/usb/Android.bp b/usb/Android.bp
index ccaa001..40454af 100644
--- a/usb/Android.bp
+++ b/usb/Android.bp
@@ -36,6 +36,7 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: [
         "libbase",
+        "libbinder",
         "libhidlbase",
         "liblog",
         "libutils",
@@ -47,8 +48,20 @@
         "android.hardware.usb.gadget@1.0",
         "android.hardware.usb.gadget@1.1",
         "android.hardware.usb.gadget@1.2",
+        "android.hardware.thermal@1.0",
+        "android.hardware.thermal@2.0",
         "libcutils",
+        "android.frameworks.stats-V1-ndk_platform",
+        "pixelatoms-cpp",
+        "libbinder_ndk",
     ],
-    static_libs: ["libpixelusb"],
+    static_libs: [
+        "libpixelusb",
+        "libpixelstats",
+    ],
+    export_shared_lib_headers: [
+        "android.frameworks.stats-V1-ndk_platform",
+        "pixelatoms-cpp",
+    ],
     proprietary: true,
 }
diff --git a/usb/Usb.cpp b/usb/Usb.cpp
index 3270c46..caf4f57 100644
--- a/usb/Usb.cpp
+++ b/usb/Usb.cpp
@@ -37,7 +37,14 @@
 #include "Usb.h"
 #include "UsbGadget.h"
 
+#include <aidl/android/frameworks/stats/IStats.h>
+#include <pixelstats/StatsHelper.h>
+
+using aidl::android::frameworks::stats::IStats;
 using android::base::GetProperty;
+using android::hardware::google::pixel::getStatsService;
+using android::hardware::google::pixel::PixelAtoms::VendorUsbPortOverheat;
+using android::hardware::google::pixel::reportUsbPortOverheat;
 
 namespace android {
 namespace hardware {
@@ -96,6 +103,13 @@
 constexpr char kStatusPath[] = "i2c-max77759tcpc/contaminant_detection_status";
 constexpr char kTypecPath[] = "/sys/class/typec";
 constexpr char kDisableContatminantDetection[] = "vendor.usb.contaminantdisable";
+constexpr char kOverheatStatsPath[] = "/sys/devices/platform/google,usbc_port_cooling_dev/";
+constexpr char kOverheatStatsDev[] = "DRIVER=google,usbc_port_cooling_dev";
+constexpr char kThermalZoneForTrip[] = "VIRTUAL-USB-THROTTLING";
+constexpr char kThermalZoneForTempReadPrimary[] = "usb_pwr_therm2";
+constexpr char kThermalZoneForTempReadSecondary1[] = "usb_pwr_therm";
+constexpr char kThermalZoneForTempReadSecondary2[] = "qi_therm";
+constexpr int kSamplingIntervalSec = 5;
 
 int32_t readFile(const std::string &filename, std::string *contents) {
     FILE *fp;
@@ -327,7 +341,15 @@
     : mLock(PTHREAD_MUTEX_INITIALIZER),
       mRoleSwitchLock(PTHREAD_MUTEX_INITIALIZER),
       mPartnerLock(PTHREAD_MUTEX_INITIALIZER),
-      mPartnerUp(false) {
+      mPartnerUp(false),
+      mOverheat(ZoneInfo(TemperatureType::USB_PORT, kThermalZoneForTrip,
+                         ThrottlingSeverity::CRITICAL),
+                {ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadPrimary,
+                          ThrottlingSeverity::NONE),
+                 ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary1,
+                          ThrottlingSeverity::NONE),
+                 ZoneInfo(TemperatureType::UNKNOWN, kThermalZoneForTempReadSecondary2,
+                          ThrottlingSeverity::NONE)}, kSamplingIntervalSec) {
     pthread_condattr_t attr;
     if (pthread_condattr_init(&attr)) {
         ALOGE("pthread_condattr_init failed: %s", strerror(errno));
@@ -525,7 +547,8 @@
  * The caller of this method would reconstruct the V1_0::PortStatus
  * object if required.
  */
-Status getPortStatusHelper(hidl_vec<PortStatus> *currentPortStatus_1_2, HALVersion version) {
+Status getPortStatusHelper(hidl_vec<PortStatus> *currentPortStatus_1_2, HALVersion version,
+                           android::hardware::usb::V1_3::implementation::Usb *usb) {
     std::unordered_map<std::string, bool> names;
     Status result = getTypeCPortNamesHelper(&names);
     int i = -1;
@@ -586,6 +609,12 @@
                 (*currentPortStatus_1_2)[i].status_1_1.status.currentMode = V1_0::PortMode::NONE;
             }
 
+            // Query temperature for the first connect
+            if (port.second && !usb->mPluggedTemperatureCelsius) {
+                usb->mOverheat.getCurrentTemperature(kThermalZoneForTempReadPrimary,
+                    &usb->mPluggedTemperatureCelsius);
+                ALOGV("USB Initial temperature: %f", usb->mPluggedTemperatureCelsius);
+            }
             ALOGI(
                 "%d:%s connected:%d canChangeMode:%d canChagedata:%d canChangePower:%d "
                 "supportedModes:%d",
@@ -612,16 +641,16 @@
     pthread_mutex_lock(&usb->mLock);
     if (usb->mCallback_1_0 != NULL) {
         if (callback_V1_2 != NULL) {
-            status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_2);
+            status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_2, usb);
             if (status == Status::SUCCESS)
                 queryMoistureDetectionStatus(currentPortStatus_1_2);
         } else if (callback_V1_1 != NULL) {
-            status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_1);
+            status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_1, usb);
             currentPortStatus_1_1.resize(currentPortStatus_1_2->size());
             for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++)
                 currentPortStatus_1_1[i] = (*currentPortStatus_1_2)[i].status_1_1;
         } else {
-            status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_0);
+            status = getPortStatusHelper(currentPortStatus_1_2, HALVersion::V1_0, usb);
             currentPortStatus.resize(currentPortStatus_1_2->size());
             for (unsigned long i = 0; i < currentPortStatus_1_2->size(); i++)
                 currentPortStatus[i] = (*currentPortStatus_1_2)[i].status_1_1.status;
@@ -673,6 +702,39 @@
     return Void();
 }
 
+void report_overheat_event(android::hardware::usb::V1_3::implementation::Usb *usb) {
+    VendorUsbPortOverheat overheat_info;
+    std::string contents;
+
+    overheat_info.set_plug_temperature_deci_c(usb->mPluggedTemperatureCelsius * 10);
+    overheat_info.set_max_temperature_deci_c(usb->mOverheat.getMaxOverheatTemperature() * 10);
+    if (ReadFileToString(std::string(kOverheatStatsPath) + "trip_time", &contents)) {
+        overheat_info.set_time_to_overheat_secs(stoi(contents));
+    } else {
+        ALOGE("Unable to read trip_time");
+        return;
+    }
+    if (ReadFileToString(std::string(kOverheatStatsPath) + "hysteresis_time", &contents)) {
+        overheat_info.set_time_to_hysteresis_secs(stoi(contents));
+    } else {
+        ALOGE("Unable to read hysteresis_time");
+        return;
+    }
+    if (ReadFileToString(std::string(kOverheatStatsPath) + "cleared_time", &contents)) {
+        overheat_info.set_time_to_inactive_secs(stoi(contents));
+    } else {
+        ALOGE("Unable to read cleared_time");
+        return;
+    }
+
+    const std::shared_ptr<IStats> stats_client = getStatsService();
+    if (!stats_client) {
+        ALOGE("Unable to get AIDL Stats service");
+    } else {
+        reportUsbPortOverheat(stats_client, overheat_info);
+    }
+}
+
 struct data {
     int uevent_fd;
     android::hardware::usb::V1_3::implementation::Usb *usb;
@@ -700,6 +762,10 @@
             payload->usb->mPartnerUp = true;
             pthread_cond_signal(&payload->usb->mPartnerCV);
             pthread_mutex_unlock(&payload->usb->mPartnerLock);
+            // Update Plugged temperature
+            payload->usb->mOverheat.getCurrentTemperature(kThermalZoneForTempReadPrimary,
+                    &payload->usb->mPluggedTemperatureCelsius);
+            ALOGI("Usb Plugged temp: %f", payload->usb->mPluggedTemperatureCelsius);
         } else if (!strncmp(cp, "DEVTYPE=typec_", strlen("DEVTYPE=typec_")) ||
                    !strncmp(cp, "DRIVER=max77759tcpc",
                             strlen("DRIVER=max77759tcpc"))) {
@@ -725,6 +791,9 @@
                 pthread_mutex_unlock(&payload->usb->mRoleSwitchLock);
             }
             break;
+        } else if (!strncmp(cp, kOverheatStatsDev, strlen(kOverheatStatsDev))) {
+            ALOGV("Overheat Cooling device suez update");
+            report_overheat_event(payload->usb);
         }
         /* advance to after the next \0 */
         while (*cp++) {
diff --git a/usb/Usb.h b/usb/Usb.h
index ab97bd0..23ed011 100644
--- a/usb/Usb.h
+++ b/usb/Usb.h
@@ -21,6 +21,7 @@
 #include <android/hardware/usb/1.2/types.h>
 #include <android/hardware/usb/1.2/IUsbCallback.h>
 #include <hidl/Status.h>
+#include <pixelusb/UsbOverheatEvent.h>
 #include <utils/Log.h>
 
 #define UEVENT_MSG_LEN 2048
@@ -36,14 +37,18 @@
 namespace V1_3 {
 namespace implementation {
 
-using ::android::sp;
+using ::android::base::WriteStringToFile;
+using ::android::base::ReadFileToString;
 using ::android::hardware::hidl_array;
 using ::android::hardware::hidl_memory;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::base::WriteStringToFile;
+using ::android::hardware::google::pixel::usb::UsbOverheatEvent;
+using ::android::hardware::google::pixel::usb::ZoneInfo;
+using ::android::hardware::thermal::V2_0::TemperatureType;
+using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
 using ::android::hardware::usb::V1_0::PortRole;
 using ::android::hardware::usb::V1_0::PortRoleType;
 using ::android::hardware::usb::V1_0::PortDataRole;
@@ -58,6 +63,7 @@
 using ::android::hardware::usb::V1_1::PortStatus_1_1;
 using ::android::hidl::base::V1_0::DebugInfo;
 using ::android::hidl::base::V1_0::IBase;
+using ::android::sp;
 
 enum class HALVersion{
     V1_0,
@@ -95,6 +101,11 @@
     // Variable to signal partner coming back online after type switch
     bool mPartnerUp;
 
+    // Usb Overheat object for push suez event
+    UsbOverheatEvent mOverheat;
+    // Temperature when connected
+    float mPluggedTemperatureCelsius;
+
   private:
     pthread_t mPoll;
 };
diff --git a/usb/android.hardware.usb@1.3-service.gs101.rc b/usb/android.hardware.usb@1.3-service.gs101.rc
index 81ae2f9..966726b 100644
--- a/usb/android.hardware.usb@1.3-service.gs101.rc
+++ b/usb/android.hardware.usb@1.3-service.gs101.rc
@@ -1,7 +1,8 @@
 service vendor.usb-hal-1-3 /vendor/bin/hw/android.hardware.usb@1.3-service.gs101
     class hal
     user system
-    group system shell mtp
+    group system shell mtp wakelock
+    capabilities WAKE_ALARM BLOCK_SUSPEND
 
 on post-fs
     chown root system /sys/class/typec/port0/power_role