Pixelstats: monitor wireless online and ptmc id by uevent

Listen to uevent directly instead of cat file node

Bug: 159098630
Test: adb shell cmd stats print-logs # stats log on
      logo:
      I statsd  : { uid(1000) 1592294521 1018321909202 (105008)0x10000->com.google.pixel[S] 0x20000->1[I]  }
Change-Id: If83817d0ece42aa938c06cd96459391d296297d0
diff --git a/pixelstats/UeventListener.cpp b/pixelstats/UeventListener.cpp
index 1a9c140..3eda04c 100644
--- a/pixelstats/UeventListener.cpp
+++ b/pixelstats/UeventListener.cpp
@@ -22,6 +22,7 @@
 #include <android-base/strings.h>
 #include <android/frameworks/stats/1.0/IStats.h>
 #include <cutils/uevent.h>
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
 #include <log/log.h>
 #include <pixelstats/UeventListener.h>
 #include <pixelstats/WlcReporter.h>
@@ -263,19 +264,13 @@
 /* ReportWlc
  * Report wireless relate  metrics when wireless charging start
  */
-void UeventListener::ReportWlc(const char *driver) {
-    if (!driver || strncmp(driver, "POWER_SUPPLY_PRESENT=", strlen("POWER_SUPPLY_PRESENT="))) {
+void UeventListener::ReportWlc(const bool pow_wireless, const bool online, const char *ptmc) {
+    if (!pow_wireless) {
         return;
     }
-    if (wireless_charging_supported_) {
-        sp<WlcReporter> wlc_reporter = new WlcReporter();
-        if (wlc_reporter != nullptr) {
-            wireless_charging_state_ =
-                    wlc_reporter->checkAndReport(wireless_charging_state_);
-        }
-    }
-}
 
+    wlc_reporter_.checkAndReport(online, ptmc);
+}
 /**
  * Report raw battery capacity, system battery capacity and associated
  * battery capacity curves. This data is collected to verify the filter
@@ -323,14 +318,14 @@
 
     if (!ReadFileToString(kTypeCPartnerPidPath.c_str(), &file_contents_pid)) {
         ALOGE("Unable to read %s - %s", kTypeCPartnerPidPath.c_str(), strerror(errno));
-	    return;
+        return;
     }
 
     if (sscanf(file_contents_pid.substr(PID_OFFSET, PID_LENGTH).c_str(), "%x", &pid) != 1) {
         ALOGE("Unable to parse pid %s from file %s to int.",
               file_contents_pid.substr(PID_OFFSET, PID_LENGTH).c_str(),
               kTypeCPartnerPidPath.c_str());
-	return;
+        return;
     }
 
     // Upload data only for chargers
@@ -372,8 +367,10 @@
     const char *driver, *product, *subsystem;
     const char *mic_break_status, *mic_degrade_status;
     const char *devpath;
-    const char *powpresent;
     bool collect_partner_id = false;
+    bool pow_online;
+    bool pow_wireless;
+    const char *pow_ptmc;
     int n;
 
     if (uevent_fd_ < 0) {
@@ -393,7 +390,8 @@
     msg[n + 1] = '\0';
 
     driver = product = subsystem = NULL;
-    mic_break_status = mic_degrade_status = devpath = powpresent = NULL;
+    mic_break_status = mic_degrade_status = devpath = pow_ptmc = NULL;
+    pow_online = pow_wireless = false;
 
     /**
      * msg is a sequence of null-terminated strings.
@@ -412,15 +410,18 @@
             mic_degrade_status = cp;
         } else if (!strncmp(cp, "DEVPATH=", strlen("DEVPATH="))) {
             devpath = cp;
-        } else if (!strncmp(cp, "POWER_SUPPLY_PRESENT=",
-                            strlen("POWER_SUPPLY_PRESENT="))) {
-            powpresent = cp;
         } else if (!strncmp(cp, "SUBSYSTEM=", strlen("SUBSYSTEM="))) {
             subsystem = cp;
         } else if (!strncmp(cp, "DEVTYPE=typec_partner", strlen("DEVTYPE=typec_partner"))) {
             collect_partner_id = true;
+        } else if (!strncmp(cp, "POWER_SUPPLY_NAME=wireless",
+                            strlen("POWER_SUPPLY_NAME=wireless"))) {
+            pow_wireless = true;
+        } else if (!strncmp(cp, "POWER_SUPPLY_ONLINE=1", strlen("POWER_SUPPLY_ONLINE=1"))) {
+            pow_online = true;
+        } else if (!strncmp(cp, "POWER_SUPPLY_PTMC_ID=", strlen("POWER_SUPPLY_PTMC_ID="))) {
+            pow_ptmc = cp;
         }
-
         /* advance to after the next \0 */
         while (*cp++) {
         }
@@ -431,7 +432,7 @@
     ReportMicStatusUevents(devpath, mic_degrade_status);
     ReportUsbPortOverheatEvent(driver);
     ReportChargeMetricsEvent(driver);
-    ReportWlc(powpresent);
+    ReportWlc(pow_wireless, pow_online, pow_ptmc);
     ReportBatteryCapacityFGEvent(subsystem);
     if (collect_partner_id) {
         ReportTypeCPartnerId();
@@ -442,29 +443,22 @@
 
 UeventListener::UeventListener(const std::string audio_uevent, const std::string ssoc_details_path,
                                const std::string overheat_path,
-                               const std::string charge_metrics_path, const std::string
-                               typec_partner_vid_path, const std::string typec_partner_pid_path)
+                               const std::string charge_metrics_path,
+                               const std::string typec_partner_vid_path,
+                               const std::string typec_partner_pid_path)
     : kAudioUevent(audio_uevent),
       kBatterySSOCPath(ssoc_details_path),
       kUsbPortOverheatPath(overheat_path),
       kChargeMetricsPath(charge_metrics_path),
       kTypeCPartnerVidPath(typec_partner_vid_path),
       kTypeCPartnerPidPath(typec_partner_pid_path),
-      uevent_fd_(-1),
-      wireless_charging_state_(false){}
+      uevent_fd_(-1) {}
 
 /* Thread function to continuously monitor uevents.
  * Exit after kMaxConsecutiveErrors to prevent spinning. */
 void UeventListener::ListenForever() {
     constexpr int kMaxConsecutiveErrors = 10;
     int consecutive_errors = 0;
-    sp<WlcReporter> wlc_reporter = new WlcReporter();
-    if (wlc_reporter != nullptr) {
-        wireless_charging_supported_ = wlc_reporter->isWlcSupported();
-    } else {
-        ALOGE("Fail to create WlcReporter.");
-        wireless_charging_supported_ = false;
-    }
 
     while (1) {
         if (ProcessUevent()) {
diff --git a/pixelstats/WlcReporter.cpp b/pixelstats/WlcReporter.cpp
index 7c9a93f..2d1717b 100644
--- a/pixelstats/WlcReporter.cpp
+++ b/pixelstats/WlcReporter.cpp
@@ -17,13 +17,14 @@
 #define LOG_TAG "pixelstats-wlc"
 
 #include <android-base/file.h>
+#include <android-base/strings.h>
+#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
 #include <log/log.h>
 #include <pixelstats/OrientationCollector.h>
 #include <pixelstats/WlcReporter.h>
 
-#define POWER_SUPPLY_SYSFS_PATH "/sys/class/power_supply/wireless/online"
-#define POWER_SUPPLY_PTMC_PATH "/sys/class/power_supply/wireless/ptmc_id"
-#define GOOGLE_PTMC_ID 72
+#define GOOGLE_PTMC_ID 0x72
+#define ID_UNKNOWN 0
 
 using android::base::ReadFileToString;
 using android::frameworks::stats::V1_0::IStats;
@@ -34,31 +35,74 @@
 namespace google {
 namespace pixel {
 
-bool WlcReporter::checkAndReport(bool isWirelessChargingLast) {
-    bool wireless_charging = isWlcOnline();
-    if (wireless_charging && !isWirelessChargingLast) {
-        doLog();
+WlcReporter::WlcStatus::WlcStatus()
+    : is_charging(false), check_charger_vendor_id(false), check_vendor_id_attempts(0) {}
+
+void WlcReporter::checkAndReport(bool online, const char *ptmc_uevent) {
+    bool wireless_charging = online;
+    bool started_wireless_charging = wireless_charging && !wlc_status_.is_charging;
+    wlc_status_.is_charging = wireless_charging;
+
+    if (started_wireless_charging) {
+        reportOrientation();
+        wlc_status_.check_vendor_id_attempts = 0;
+        wlc_status_.check_charger_vendor_id = true;
     }
-    return wireless_charging;
+    if (!wireless_charging) {
+        wlc_status_.check_charger_vendor_id = false;
+    }
+    if (wireless_charging) {
+        checkVendorId(ptmc_uevent);
+    }
 }
 
-bool WlcReporter::readFileToInt(const char *const path, int *val) {
-    std::string file_contents;
+void WlcReporter::checkVendorId(const char *ptmc_uevent) {
+    if (!ptmc_uevent || !wlc_status_.check_charger_vendor_id) {
+        return;
+    }
+    if (reportVendor(ptmc_uevent)) {
+        wlc_status_.check_charger_vendor_id = false;
+    }
+}
 
-    if (!ReadFileToString(path, &file_contents)) {
-        ALOGE("Unable to read %s - %s", path, strerror(errno));
-        return false;
-    } else if (sscanf(file_contents.c_str(), "%d", val) != 1) {
-        ALOGE("Unable to convert %s (%s) to int - %s", path, file_contents.c_str(),
-              strerror(errno));
-        return false;
+bool WlcReporter::reportVendor(const char *ptmc_uevent) {
+    int ptmcId = readPtmcId(ptmc_uevent);
+    if (ptmcId == ID_UNKNOWN) {
+        if (++(wlc_status_.check_vendor_id_attempts) < kMaxVendorIdAttempts) {
+            return false;
+        } /* else if ptmc not ready after retry assume ptmc not supported by charger */
+    }
+    sp<IStats> stats_client = IStats::tryGetService();
+    std::vector<VendorAtom::Value> values(1);
+
+    if (stats_client == nullptr) {
+        ALOGE("logWlc get IStats fail.");
+        return true;
+    }
+
+    int vendorCharger = (ptmcId == GOOGLE_PTMC_ID)
+                                ? PixelAtoms::WirelessChargingStats::VENDOR_GOOGLE
+                                : PixelAtoms::WirelessChargingStats::VENDOR_UNKNOWN;
+    VendorAtom::Value tmp;
+    tmp.intValue(vendorCharger);
+    values[PixelAtoms::WirelessChargingStats::kChargerVendorFieldNumber - kVendorAtomOffset] = tmp;
+
+    // Send vendor atom to IStats HAL
+    VendorAtom event = {.reverseDomainName = PixelAtoms::ReverseDomainNames().pixel(),
+                        .atomId = PixelAtoms::Ids::WIRELESS_CHARGING_STATS,
+                        .values = values};
+    Return<void> retStat = stats_client->reportVendorAtom(event);
+    if (!retStat.isOk()) {
+        ALOGE("Unable to report WLC_STATS to Stats service");
     }
     return true;
 }
 
-int WlcReporter::readPtmcId() {
-    int id = 0;
-    readFileToInt(POWER_SUPPLY_PTMC_PATH, &id);
+int WlcReporter::readPtmcId(const char *ptmc_uevent) {
+    int id;
+    if (sscanf(ptmc_uevent, "POWER_SUPPLY_PTMC_ID=%x", &id) != 1) {
+        return ID_UNKNOWN;
+    }
     return id;
 }
 
@@ -81,7 +125,7 @@
     }
 }
 
-void WlcReporter::doLog() {
+void WlcReporter::reportOrientation() {
     sp<IStats> stats_client = IStats::tryGetService();
 
     if (stats_client == nullptr) {
@@ -90,20 +134,6 @@
     }
     std::vector<VendorAtom::Value> values(1);
 
-    int vendoriCharger = (readPtmcId() == GOOGLE_PTMC_ID)
-                                 ? PixelAtoms::WirelessChargingStats::VENDOR_GOOGLE
-                                 : PixelAtoms::WirelessChargingStats::VENDOR_UNKNOWN;
-    VendorAtom::Value tmp;
-    tmp.intValue(vendoriCharger);
-    values[PixelAtoms::WirelessChargingStats::kChargerVendorFieldNumber - kVendorAtomOffset] = tmp;
-
-    // Send vendor atom to IStats HAL
-    VendorAtom event = {.reverseDomainName = PixelAtoms::ReverseDomainNames().pixel(),
-                        .atomId = PixelAtoms::Ids::WIRELESS_CHARGING_STATS,
-                        .values = values};
-    Return<void> retStat = stats_client->reportVendorAtom(event);
-    if (!retStat.isOk())
-        ALOGE("Unable to report WLC_STATS to Stats service");
 
     int orientationFromSensor;
     sp<OrientationCollector> orientationCollector;
@@ -124,28 +154,6 @@
     }
 }
 
-bool WlcReporter::isWlcSupported() {
-    std::string file_contents;
-
-    if (!ReadFileToString(POWER_SUPPLY_SYSFS_PATH, &file_contents)) {
-        ALOGV("Unable to read %s - %s", POWER_SUPPLY_SYSFS_PATH, strerror(errno));
-        return false;
-    } else {
-        return true;
-    }
-}
-
-bool WlcReporter::isWlcOnline() {
-    std::string file_contents;
-
-    if (!ReadFileToString(POWER_SUPPLY_SYSFS_PATH, &file_contents)) {
-        ALOGE("Unable to read %s - %s", POWER_SUPPLY_SYSFS_PATH, strerror(errno));
-        return false;
-    }
-    ALOGV("isWlcOnline value: %s", file_contents.c_str());
-    return file_contents == "1\n";
-}
-
 }  // namespace pixel
 }  // namespace google
 }  // namespace hardware
diff --git a/pixelstats/include/pixelstats/UeventListener.h b/pixelstats/include/pixelstats/UeventListener.h
index 82dc14a..e8e9457 100644
--- a/pixelstats/include/pixelstats/UeventListener.h
+++ b/pixelstats/include/pixelstats/UeventListener.h
@@ -20,6 +20,7 @@
 #include <android-base/chrono_utils.h>
 #include <android/frameworks/stats/1.0/IStats.h>
 #include <pixelstats/BatteryCapacityReporter.h>
+#include <pixelstats/WlcReporter.h>
 
 using android::frameworks::stats::V1_0::IStats;
 using android::frameworks::stats::V1_0::UsbPortOverheatEvent;
@@ -42,8 +43,10 @@
             const std::string overheat_path =
                     "/sys/devices/platform/soc/soc:google,overheat_mitigation",
             const std::string charge_metrics_path = "/sys/class/power_supply/battery/charge_stats",
-            const std::string typec_partner_vid_path = "/sys/class/typec/port0-partner/identity/id_header",
-            const std::string typec_partner_pid_path = "/sys/class/typec/port0-partner/identity/product");
+            const std::string typec_partner_vid_path =
+                    "/sys/class/typec/port0-partner/identity/id_header",
+            const std::string typec_partner_pid_path =
+                    "/sys/class/typec/port0-partner/identity/product");
 
     bool ProcessUevent();  // Process a single Uevent.
     void ListenForever();  // Process Uevents forever
@@ -57,7 +60,7 @@
     void ReportChargeStats(const sp<IStats> &stats_client, const char *line);
     void ReportVoltageTierStats(const sp<IStats> &stats_client, const char *line);
     void ReportChargeMetricsEvent(const char *driver);
-    void ReportWlc(const char *driver);
+    void ReportWlc(const bool pow_wireless, const bool online, const char *ptmc);
     void ReportBatteryCapacityFGEvent(const char *subsystem);
     void ReportTypeCPartnerId();
 
@@ -77,8 +80,7 @@
 
     int uevent_fd_;
 
-    bool wireless_charging_state_;
-    bool wireless_charging_supported_;
+    WlcReporter wlc_reporter_;
 };
 
 }  // namespace pixel
diff --git a/pixelstats/include/pixelstats/WlcReporter.h b/pixelstats/include/pixelstats/WlcReporter.h
index d29b7b4..0418247 100644
--- a/pixelstats/include/pixelstats/WlcReporter.h
+++ b/pixelstats/include/pixelstats/WlcReporter.h
@@ -18,7 +18,6 @@
 #define HARDWARE_GOOGLE_PIXEL_PIXELSTATS_WLCREPORTER_H
 
 #include <android/frameworks/stats/1.0/IStats.h>
-#include <hardware/google/pixel/pixelstats/pixelatoms.pb.h>
 
 using android::frameworks::stats::V1_0::IStats;
 
@@ -32,19 +31,21 @@
  */
 class WlcReporter : public RefBase {
   public:
-    /* checkAndReport
-     * isWirelessChargingLast: last wireless charge state
-     *                             true, for wireless charging
-     * Return: current wireless charge state
-     */
-    bool checkAndReport(bool isWirelessChargingLast);
-    bool isWlcSupported();
+    void checkAndReport(const bool online, const char *ptmc_uevent);
 
   private:
-    bool isWlcOnline();
-    bool readFileToInt(const char *path, int *val);
+    struct WlcStatus {
+        bool is_charging;
+        bool check_charger_vendor_id;
+        int check_vendor_id_attempts;
+        WlcStatus();
+    };
+    WlcStatus wlc_status_;
 
-    void doLog();
+    void checkVendorId(const char *ptmc_uevent);
+
+    void reportOrientation();
+    bool reportVendor(const char *ptmc_uevent);
     // Translate device orientation value from sensor Hal to atom enum value
     int translateDeviceOrientationToAtomValue(int orientation);
 
@@ -52,7 +53,9 @@
     // store everything in the values array at the index of the field number
     // -2.
     const int kVendorAtomOffset = 2;
-    int readPtmcId();
+    const int kMaxVendorIdAttempts = 5;
+
+    int readPtmcId(const char *ptmc_uevent);
 };
 
 }  // namespace pixel