logd: liblog: logcat: Arbitrary time to tail

Change-Id: I10e8d92c933e31ee11e78d2d1114261a30c4be0e
diff --git a/logd/FlushCommand.cpp b/logd/FlushCommand.cpp
index 0b8c31b..3be07c0 100644
--- a/logd/FlushCommand.cpp
+++ b/logd/FlushCommand.cpp
@@ -26,12 +26,14 @@
                            bool nonBlock,
                            unsigned long tail,
                            unsigned int logMask,
-                           pid_t pid)
+                           pid_t pid,
+                           log_time start)
         : mReader(reader)
         , mNonBlock(nonBlock)
         , mTail(tail)
         , mLogMask(logMask)
         , mPid(pid)
+        , mStart(start)
 { }
 
 // runSocketCommand is called once for every open client on the
@@ -69,7 +71,7 @@
             LogTimeEntry::unlock();
             return;
         }
-        entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid);
+        entry = new LogTimeEntry(mReader, client, mNonBlock, mTail, mLogMask, mPid, mStart);
         times.push_back(entry);
     }
 
diff --git a/logd/FlushCommand.h b/logd/FlushCommand.h
index 715daac..f34c06a 100644
--- a/logd/FlushCommand.h
+++ b/logd/FlushCommand.h
@@ -16,8 +16,13 @@
 #ifndef _FLUSH_COMMAND_H
 #define _FLUSH_COMMAND_H
 
+#include <log/log_read.h>
 #include <sysutils/SocketClientCommand.h>
 
+class LogBufferElement;
+
+#include "LogTimes.h"
+
 class LogReader;
 
 class FlushCommand : public SocketClientCommand {
@@ -26,13 +31,15 @@
     unsigned long mTail;
     unsigned int mLogMask;
     pid_t mPid;
+    log_time mStart;
 
 public:
     FlushCommand(LogReader &mReader,
                  bool nonBlock = false,
                  unsigned long tail = -1,
                  unsigned int logMask = -1,
-                 pid_t pid = 0);
+                 pid_t pid = 0,
+                 log_time start = LogTimeEntry::EPOCH);
     virtual void runSocketCommand(SocketClient *client);
 
     static bool hasReadLogs(SocketClient *client);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 01cc9de..8d45f34 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -24,7 +24,7 @@
 #include "LogBufferElement.h"
 #include "LogReader.h"
 
-const log_time LogBufferElement::FLUSH_ERROR(0, 0);
+const log_time LogBufferElement::FLUSH_ERROR((uint32_t)0, (uint32_t)0);
 
 LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime,
                                    uid_t uid, pid_t pid, const char *msg,
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 5b540bf..29bfbda 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
 #include <poll.h>
 #include <sys/socket.h>
 #include <cutils/sockets.h>
@@ -50,6 +51,14 @@
         tail = atol(cp + sizeof(_tail) - 1);
     }
 
+    log_time start(log_time::EPOCH);
+    static const char _start[] = " start=";
+    cp = strstr(buffer, _start);
+    if (cp) {
+        // Parse errors will result in current time
+        start.strptime(cp + sizeof(_start) - 1, "%s.%q");
+    }
+
     unsigned int logMask = -1;
     static const char _logIds[] = " lids=";
     cp = strstr(buffer, _logIds);
@@ -58,9 +67,8 @@
         cp += sizeof(_logIds) - 1;
         while (*cp && *cp != '\0') {
             int val = 0;
-            while (('0' <= *cp) && (*cp <= '9')) {
-                val *= 10;
-                val += *cp - '0';
+            while (isdigit(*cp)) {
+                val = val * 10 + *cp - '0';
                 ++cp;
             }
             logMask |= 1 << val;
@@ -83,7 +91,18 @@
         nonBlock = true;
     }
 
-    FlushCommand command(*this, nonBlock, tail, logMask, pid);
+    // Convert realtime to monotonic time
+    if (start != log_time::EPOCH) {
+        log_time real(CLOCK_REALTIME);
+        log_time monotonic(CLOCK_MONOTONIC);
+        real -= monotonic; // I know this is not 100% accurate
+        start -= real;
+    }
+    if (start == log_time::EPOCH) {
+        start = LogTimeEntry::EPOCH;
+    }
+
+    FlushCommand command(*this, nonBlock, tail, logMask, pid, start);
     command.runSocketCommand(cli);
     return true;
 }
diff --git a/logd/LogTimes.cpp b/logd/LogTimes.cpp
index 67cc65e..8cb015c 100644
--- a/logd/LogTimes.cpp
+++ b/logd/LogTimes.cpp
@@ -25,7 +25,8 @@
 
 LogTimeEntry::LogTimeEntry(LogReader &reader, SocketClient *client,
                            bool nonBlock, unsigned long tail,
-                           unsigned int logMask, pid_t pid)
+                           unsigned int logMask, pid_t pid,
+                           log_time start)
         : mRefCount(1)
         , mRelease(false)
         , mError(false)
@@ -39,7 +40,7 @@
         , mTail(tail)
         , mIndex(0)
         , mClient(client)
-        , mStart(EPOCH)
+        , mStart(start)
         , mNonBlock(nonBlock)
         , mEnd(CLOCK_MONOTONIC)
 { }
diff --git a/logd/LogTimes.h b/logd/LogTimes.h
index cb6f566..beaf646 100644
--- a/logd/LogTimes.h
+++ b/logd/LogTimes.h
@@ -45,7 +45,8 @@
 
 public:
     LogTimeEntry(LogReader &reader, SocketClient *client, bool nonBlock,
-                 unsigned long tail, unsigned int logMask, pid_t pid);
+                 unsigned long tail, unsigned int logMask, pid_t pid,
+                 log_time start);
 
     SocketClient *mClient;
     static const struct timespec EPOCH;