liblog: logprint add uid format modifier

Bug: 25996918
Change-Id: Idff5e080fc5c7b69e0c45d3f596eb9d632451cbd
diff --git a/include/log/logprint.h b/include/log/logprint.h
index 204b3f2..539d1dc 100644
--- a/include/log/logprint.h
+++ b/include/log/logprint.h
@@ -44,6 +44,7 @@
     FORMAT_MODIFIER_ZONE,      /* Adds zone to date */
     FORMAT_MODIFIER_EPOCH,     /* Print time as seconds since Jan 1 1970 */
     FORMAT_MODIFIER_MONOTONIC, /* Print cpu time as seconds since start */
+    FORMAT_MODIFIER_UID,       /* Adds uid */
 } AndroidLogPrintFormat;
 
 typedef struct AndroidLogFormat_t AndroidLogFormat;
@@ -52,6 +53,7 @@
     time_t tv_sec;
     long tv_nsec;
     android_LogPriority priority;
+    int32_t uid;
     int32_t pid;
     int32_t tid;
     const char * tag;
diff --git a/liblog/logprint.c b/liblog/logprint.c
index 40e13f4..b745cf6 100644
--- a/liblog/logprint.c
+++ b/liblog/logprint.c
@@ -56,6 +56,7 @@
     bool zone_output;
     bool epoch_output;
     bool monotonic_output;
+    bool uid_output;
 };
 
 /*
@@ -204,6 +205,7 @@
     p_ret->zone_output = false;
     p_ret->epoch_output = false;
     p_ret->monotonic_output = android_log_clockid() == CLOCK_MONOTONIC;
+    p_ret->uid_output = false;
 
     return p_ret;
 }
@@ -258,6 +260,9 @@
     case FORMAT_MODIFIER_MONOTONIC:
         p_format->monotonic_output = true;
         return 0;
+    case FORMAT_MODIFIER_UID:
+        p_format->uid_output = true;
+        return 0;
     default:
         break;
     }
@@ -290,6 +295,7 @@
     else if (strcmp(formatString, "zone") == 0) format = FORMAT_MODIFIER_ZONE;
     else if (strcmp(formatString, "epoch") == 0) format = FORMAT_MODIFIER_EPOCH;
     else if (strcmp(formatString, "monotonic") == 0) format = FORMAT_MODIFIER_MONOTONIC;
+    else if (strcmp(formatString, "uid") == 0) format = FORMAT_MODIFIER_UID;
     else {
         extern char *tzname[2];
         static const char gmt[] = "GMT";
@@ -451,6 +457,7 @@
 {
     entry->tv_sec = buf->sec;
     entry->tv_nsec = buf->nsec;
+    entry->uid = -1;
     entry->pid = buf->pid;
     entry->tid = buf->tid;
 
@@ -482,6 +489,9 @@
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
         msg = ((char *)buf2) + buf2->hdr_size;
+        if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
+            entry->uid = ((struct logger_entry_v4 *)buf)->uid;
+        }
     }
     for (i = 1; i < buf->len; i++) {
         if (msg[i] == '\0') {
@@ -734,6 +744,7 @@
     entry->tv_sec = buf->sec;
     entry->tv_nsec = buf->nsec;
     entry->priority = ANDROID_LOG_INFO;
+    entry->uid = -1;
     entry->pid = buf->pid;
     entry->tid = buf->tid;
 
@@ -744,6 +755,9 @@
     struct logger_entry_v2 *buf2 = (struct logger_entry_v2 *)buf;
     if (buf2->hdr_size) {
         eventData = ((unsigned char *)buf2) + buf2->hdr_size;
+        if (buf2->hdr_size >= sizeof(struct logger_entry_v4)) {
+            entry->uid = ((struct logger_entry_v4 *)buf)->uid;
+        }
     }
     inCount = buf->len;
     if (inCount < 4)
@@ -1238,7 +1252,7 @@
     char prefixBuf[128], suffixBuf[128];
     char priChar;
     int prefixSuffixIsHeaderFooter = 0;
-    char *ret = NULL;
+    char *ret;
     time_t now;
     unsigned long nsec;
 
@@ -1310,6 +1324,16 @@
         suffixLen = MIN(suffixLen, sizeof(suffixBuf));
     }
 
+    char uid[16];
+    uid[0] = '\0';
+    if (p_format->uid_output) {
+        if (entry->uid >= 0) {
+            snprintf(uid, sizeof(uid), "%5d:", entry->uid);
+        } else {
+            snprintf(uid, sizeof(uid), "      ");
+        }
+    }
+
     switch (p_format->format) {
         case FORMAT_TAG:
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
@@ -1322,11 +1346,11 @@
                 "  (%s)\n", entry->tag);
             suffixLen += MIN(len, sizeof(suffixBuf) - suffixLen);
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
-                "%c(%5d) ", priChar, entry->pid);
+                "%c(%s%5d) ", priChar, uid, entry->pid);
             break;
         case FORMAT_THREAD:
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
-                "%c(%5d:%5d) ", priChar, entry->pid, entry->tid);
+                "%c(%s%5d:%5d) ", priChar, uid, entry->pid, entry->tid);
             strcpy(suffixBuf + suffixLen, "\n");
             ++suffixLen;
             break;
@@ -1338,21 +1362,26 @@
             break;
         case FORMAT_TIME:
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
-                "%s %c/%-8s(%5d): ", timeBuf, priChar, entry->tag, entry->pid);
+                "%s %c/%-8s(%s%5d): ", timeBuf, priChar, entry->tag,
+                uid, entry->pid);
             strcpy(suffixBuf + suffixLen, "\n");
             ++suffixLen;
             break;
         case FORMAT_THREADTIME:
+            ret = strchr(uid, ':');
+            if (ret) {
+                *ret = ' ';
+            }
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
-                "%s %5d %5d %c %-8s: ", timeBuf,
-                entry->pid, entry->tid, priChar, entry->tag);
+                "%s %s%5d %5d %c %-8s: ", timeBuf,
+                uid, entry->pid, entry->tid, priChar, entry->tag);
             strcpy(suffixBuf + suffixLen, "\n");
             ++suffixLen;
             break;
         case FORMAT_LONG:
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
-                "[ %s %5d:%5d %c/%-8s ]\n",
-                timeBuf, entry->pid, entry->tid, priChar, entry->tag);
+                "[ %s %s%5d:%5d %c/%-8s ]\n",
+                timeBuf, uid, entry->pid, entry->tid, priChar, entry->tag);
             strcpy(suffixBuf + suffixLen, "\n\n");
             suffixLen += 2;
             prefixSuffixIsHeaderFooter = 1;
@@ -1360,7 +1389,7 @@
         case FORMAT_BRIEF:
         default:
             len = snprintf(prefixBuf + prefixLen, sizeof(prefixBuf) - prefixLen,
-                "%c/%-8s(%5d): ", priChar, entry->tag, entry->pid);
+                "%c/%-8s(%s%5d): ", priChar, entry->tag, uid, entry->pid);
             strcpy(suffixBuf + suffixLen, "\n");
             ++suffixLen;
             break;
diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp
index 059916e..32bfd9c 100644
--- a/logcat/logcat.cpp
+++ b/logcat/logcat.cpp
@@ -265,7 +265,7 @@
                     "  -v <format>     Sets the log print format, where <format> is:\n"
                     "  --format=<format>\n"
                     "                      brief color epoch long monotonic printable process raw\n"
-                    "                      tag thread threadtime time usec UTC year zone\n\n"
+                    "                      tag thread threadtime time uid usec UTC year zone\n\n"
                     "  -D              print dividers between each log buffer\n"
                     "  --dividers\n"
                     "  -c              clear (flush) the entire log and exit\n"