logd: remove FlushCommand

This code has evolved to the point that it LogReader::notifyNewLog()
executes FlushCommand on every socket.  FlushCommand then iterates
over all log reader threads in LogTimes and flushes triggers them to
flush logs if they match the client.  This can be simplified to simply
looping over all of the reads in LogTimes.

Code readability was the primary motivation here, but note that 64% of
LogReader::notifyNewLog() was spent looping over the sockets, and an
additional 78% of FlushCommand::runSocketCommand() was spent
repeatedly locking and unlocking the LogTimes lock.

Overall, this reduces the cost of LogReader::notifyNewLog() in
LogListener::onDataAvailable() from 5.91% to 2.93%.  This is the
critical path for handling incoming log messages, so it's a
non-trivial savings.

Test: logging unit tests
Test: unprivileged clients still cannot view privileged logs
Change-Id: Ic7620978a6c23e5e2cb179ff0c42b7cea52fc011
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index f79d39c..c6dea69 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -24,21 +24,35 @@
 #include <cutils/sockets.h>
 #include <private/android_logger.h>
 
-#include "FlushCommand.h"
 #include "LogBuffer.h"
 #include "LogBufferElement.h"
 #include "LogReader.h"
 #include "LogUtils.h"
 
+static bool CanReadSecurityLogs(SocketClient* client) {
+    return client->getUid() == AID_SYSTEM || client->getGid() == AID_SYSTEM;
+}
+
 LogReader::LogReader(LogBuffer* logbuf)
     : SocketListener(getLogSocket(), true), mLogbuf(*logbuf) {
 }
 
 // When we are notified a new log entry is available, inform
 // listening sockets who are watching this entry's log id.
-void LogReader::notifyNewLog(log_mask_t logMask) {
-    FlushCommand command(*this, logMask);
-    runOnEachSocket(&command);
+void LogReader::notifyNewLog(log_mask_t log_mask) {
+    LastLogTimes& times = mLogbuf.mTimes;
+
+    LogTimeEntry::wrlock();
+    for (const auto& entry : times) {
+        if (!entry->isWatchingMultiple(log_mask)) {
+            continue;
+        }
+        if (entry->mTimeout.tv_sec || entry->mTimeout.tv_nsec) {
+            continue;
+        }
+        entry->triggerReader_Locked();
+    }
+    LogTimeEntry::unlock();
 }
 
 // Note returning false will release the SocketClient instance.
@@ -129,6 +143,9 @@
         nonBlock = true;
     }
 
+    bool privileged = clientHasLogCredentials(cli);
+    bool can_read_security = CanReadSecurityLogs(cli);
+
     uint64_t sequence = 1;
     // Convert realtime to sequence number
     if (start != log_time::EPOCH) {
@@ -178,8 +195,7 @@
         } logFindStart(logMask, pid, start, sequence,
                        logbuf().isMonotonic() && android::isMonotonic(start));
 
-        logbuf().flushTo(cli, sequence, nullptr, FlushCommand::hasReadLogs(cli),
-                         FlushCommand::hasSecurityLogs(cli),
+        logbuf().flushTo(cli, sequence, nullptr, privileged, can_read_security,
                          logFindStart.callback, &logFindStart);
 
         if (!logFindStart.found()) {
@@ -203,7 +219,7 @@
 
     LogTimeEntry::wrlock();
     auto entry = std::make_unique<LogTimeEntry>(*this, cli, nonBlock, tail, logMask, pid, start,
-                                                sequence, timeout);
+                                                sequence, timeout, privileged, can_read_security);
     if (!entry->startReader_Locked()) {
         LogTimeEntry::unlock();
         return false;