logd: Add pidToName helper

Change-Id: Idd8e804ab65feb8dc432150ae701464de1ad5302
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index c3460ca..7c57660 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -77,6 +77,9 @@
     void formatPrune(char **strp) { mPrune.format(strp); }
 #endif
 
+    // helper
+    char *pidToName(pid_t pid) { return stats.pidToName(pid); }
+
 private:
     void maybePrune(log_id_t id);
     void prune(log_id_t id, unsigned long pruneRows);
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 5622ee5..99c376a 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <fcntl.h>
 #include <stdarg.h>
 #include <time.h>
 
@@ -23,12 +24,34 @@
 
 #include "LogStatistics.h"
 
-PidStatistics::PidStatistics(pid_t pid)
+PidStatistics::PidStatistics(pid_t pid, char *name)
         : pid(pid)
         , mSizesTotal(0)
         , mElementsTotal(0)
         , mSizes(0)
-        , mElements(0) { }
+        , mElements(0)
+        , name(name)
+{ }
+
+#ifdef DO_NOT_ERROR_IF_PIDSTATISTICS_USES_A_COPY_CONSTRUCTOR
+PidStatistics::PidStatistics(const PidStatistics &copy)
+        : pid(copy->pid)
+        , name(copy->name ? strdup(copy->name) : NULL)
+        , mSizesTotal(copy->mSizesTotal)
+        , mElementsTotal(copy->mElementsTotal)
+        , mSizes(copy->mSizes)
+        , mElements(copy->mElements)
+{ }
+#endif
+
+PidStatistics::~PidStatistics() {
+    free(name);
+}
+
+void PidStatistics::setName(char *new_name) {
+    free(name);
+    name = new_name;
+}
 
 void PidStatistics::add(unsigned short size) {
     mSizesTotal += size;
@@ -50,6 +73,28 @@
     }
 }
 
+// must call free to release return value
+char *PidStatistics::pidToName(pid_t pid) {
+    char *retval = NULL;
+    if (pid != PidStatistics::gone) {
+        char buffer[512];
+        snprintf(buffer, sizeof(buffer), "/proc/%u/cmdline", pid);
+        int fd = open(buffer, O_RDONLY);
+        if (fd >= 0) {
+            ssize_t ret = read(fd, buffer, sizeof(buffer));
+            if (ret > 0) {
+                buffer[sizeof(buffer)-1] = '\0';
+                // frameworks intermediate state
+                if (strcmp(buffer, "<pre-initialized>")) {
+                    retval = strdup(buffer);
+                }
+            }
+            close(fd);
+        }
+    }
+    return retval;
+}
+
 UidStatistics::UidStatistics(uid_t uid)
         : uid(uid) {
     Pids.clear();
@@ -83,7 +128,7 @@
     bool insert = (last != it)
         && ((p->getPid() == p->gone)
             || ((*last)->sizesTotal() < (size_t) size));
-    p = new PidStatistics(pid);
+    p = new PidStatistics(pid, pidToName(pid));
     if (insert) {
         Pids.insert(last, p);
     } else {
@@ -397,8 +442,8 @@
 
 void LogStatistics::format(char **buf,
                            uid_t uid, unsigned int logMask, log_time oldest) {
-    const unsigned short spaces_current = 13;
-    const unsigned short spaces_total = 19;
+    static const unsigned short spaces_current = 13;
+    static const unsigned short spaces_total = 19;
 
     if (*buf) {
         free(buf);
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 6a26263..4a57435 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -36,12 +36,18 @@
     size_t mSizes;
     size_t mElements;
 
+    char *name;
+
 public:
     static const pid_t gone = (pid_t) -1;
 
-    PidStatistics(pid_t pid);
+    PidStatistics(pid_t pid, char *name = NULL);
+    PidStatistics(const PidStatistics &copy);
+    ~PidStatistics();
 
     pid_t getPid() const { return pid; }
+    char *getName() const { return name; }
+    void setName(char *name);
 
     void add(unsigned short size);
     bool subtract(unsigned short size); // returns true if stats and PID gone
@@ -52,6 +58,9 @@
 
     size_t sizesTotal() const { return mSizesTotal; }
     size_t elementsTotal() const { return mElementsTotal; }
+
+    // helper
+    static char *pidToName(pid_t pid);
 };
 
 typedef android::List<PidStatistics *> PidStatisticsCollection;
@@ -80,6 +89,9 @@
 
     size_t sizesTotal(pid_t pid = pid_all);
     size_t elementsTotal(pid_t pid = pid_all);
+
+    // helper
+    static char *pidToName(pid_t pid) { return PidStatistics::pidToName(pid); }
 };
 
 typedef android::List<UidStatistics *> UidStatisticsCollection;
@@ -157,6 +169,9 @@
 
     // *strp = malloc, balance with free
     void format(char **strp, uid_t uid, unsigned int logMask, log_time oldest);
+
+    // helper
+    static char *pidToName(pid_t pid) { return PidStatistics::pidToName(pid); }
 };
 
 #endif // _LOGD_LOG_STATISTICS_H__