storaged: add support for ufs health info

Test: adb logcat -d -b events | grep storaged_emmc_info
Bug: 36228467
Merged-In: I519fe2b8a99c1c31f1fe720bd671904d1ab609bb
Change-Id: I519fe2b8a99c1c31f1fe720bd671904d1ab609bb
diff --git a/storaged/include/storaged_info.h b/storaged/include/storaged_info.h
index cfcdd7f..913c814 100644
--- a/storaged/include/storaged_info.h
+++ b/storaged/include/storaged_info.h
@@ -52,6 +52,14 @@
     bool report_debugfs();
 };
 
+class ufs_info_t : public storage_info_t {
+private:
+    const string health_file = "/sys/devices/soc/624000.ufshc/health";
+public:
+    virtual ~ufs_info_t() {}
+    bool report();
+};
+
 void report_storage_health();
 
 #endif /* _STORAGED_INFO_H_ */
diff --git a/storaged/storaged_info.cpp b/storaged/storaged_info.cpp
index 1a5da41..434bd74 100644
--- a/storaged/storaged_info.cpp
+++ b/storaged/storaged_info.cpp
@@ -22,6 +22,7 @@
 #include <android-base/file.h>
 #include <android-base/parseint.h>
 #include <android-base/logging.h>
+#include <android-base/strings.h>
 #include <log/log_event_list.h>
 
 #include "storaged.h"
@@ -32,7 +33,10 @@
 void report_storage_health()
 {
     emmc_info_t mmc;
+    ufs_info_t ufs;
+
     mmc.report();
+    ufs.report();
 }
 
 void storage_info_t::publish()
@@ -130,4 +134,51 @@
     }
 
     return true;
-}
\ No newline at end of file
+}
+
+bool ufs_info_t::report()
+{
+    string buffer;
+    if (!ReadFileToString(health_file, &buffer)) {
+        return false;
+    }
+
+    vector<string> lines = Split(buffer, "\n");
+    if (lines.empty()) {
+        return false;
+    }
+
+    char rev[8];
+    if (sscanf(lines[0].c_str(), "ufs version: 0x%7s\n", rev) < 1) {
+        return false;
+    }
+
+    version = "ufs " + string(rev);
+
+    for (size_t i = 1; i < lines.size(); i++) {
+        char token[32];
+        uint16_t val;
+        int ret;
+        if ((ret = sscanf(lines[i].c_str(),
+                   "Health Descriptor[Byte offset 0x%*d]: %31s = 0x%hx",
+                   token, &val)) < 2) {
+            continue;
+        }
+
+        if (string(token) == "bPreEOLInfo") {
+            eol = val;
+        } else if (string(token) == "bDeviceLifeTimeEstA") {
+            lifetime_a = val;
+        } else if (string(token) == "bDeviceLifeTimeEstB") {
+            lifetime_b = val;
+        }
+    }
+
+    if (eol == 0 || (lifetime_a == 0 && lifetime_b == 0)) {
+        return false;
+    }
+
+    publish();
+    return true;
+}
+