Merge "libsparse: Limit block size to 64 MB"
diff --git a/adb/client/incremental.cpp b/adb/client/incremental.cpp
index 1e985ed..3033059 100644
--- a/adb/client/incremental.cpp
+++ b/adb/client/incremental.cpp
@@ -180,7 +180,7 @@
     int print_fds[2];
     if (adb_socketpair(print_fds) != 0) {
         if (!silent) {
-            fprintf(stderr, "Failed to create socket pair for child to print to parent\n");
+            fprintf(stderr, "adb: failed to create socket pair for child to print to parent\n");
         }
         return {};
     }
@@ -207,10 +207,15 @@
     Result result = wait_for_installation(pipe_read_fd);
     adb_close(pipe_read_fd);
 
-    if (result == Result::Success) {
-        // adb client exits now but inc-server can continue
-        serverKiller.release();
+    if (result != Result::Success) {
+        if (!silent) {
+            fprintf(stderr, "adb: install command failed");
+        }
+        return {};
     }
+
+    // adb client exits now but inc-server can continue
+    serverKiller.release();
     return child;
 }
 
diff --git a/init/first_stage_init.cpp b/init/first_stage_init.cpp
index 1a608f6..0215576 100644
--- a/init/first_stage_init.cpp
+++ b/init/first_stage_init.cpp
@@ -24,6 +24,7 @@
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 #include <sys/types.h>
+#include <sys/utsname.h>
 #include <unistd.h>
 
 #include <filesystem>
@@ -99,6 +100,77 @@
 
 }  // namespace
 
+std::string GetModuleLoadList(bool recovery, const std::string& dir_path) {
+    auto module_load_file = "modules.load";
+    if (recovery) {
+        struct stat fileStat;
+        std::string recovery_load_path = dir_path + "/modules.load.recovery";
+        if (!stat(recovery_load_path.c_str(), &fileStat)) {
+            module_load_file = "modules.load.recovery";
+        }
+    }
+
+    return module_load_file;
+}
+
+#define MODULE_BASE_DIR "/lib/modules"
+bool LoadKernelModules(bool recovery, bool want_console) {
+    struct utsname uts;
+    if (uname(&uts)) {
+        LOG(FATAL) << "Failed to get kernel version.";
+    }
+    int major, minor;
+    if (sscanf(uts.release, "%d.%d", &major, &minor) != 2) {
+        LOG(FATAL) << "Failed to parse kernel version " << uts.release;
+    }
+
+    std::unique_ptr<DIR, decltype(&closedir)> base_dir(opendir(MODULE_BASE_DIR), closedir);
+    if (!base_dir) {
+        LOG(INFO) << "Unable to open /lib/modules, skipping module loading.";
+        return true;
+    }
+    dirent* entry;
+    std::vector<std::string> module_dirs;
+    while ((entry = readdir(base_dir.get()))) {
+        if (entry->d_type != DT_DIR) {
+            continue;
+        }
+        int dir_major, dir_minor;
+        if (sscanf(entry->d_name, "%d.%d", &dir_major, &dir_minor) != 2 || dir_major != major ||
+            dir_minor != minor) {
+            continue;
+        }
+        module_dirs.emplace_back(entry->d_name);
+    }
+
+    // Sort the directories so they are iterated over during module loading
+    // in a consistent order. Alphabetical sorting is fine here because the
+    // kernel version at the beginning of the directory name must match the
+    // current kernel version, so the sort only applies to a label that
+    // follows the kernel version, for example /lib/modules/5.4 vs.
+    // /lib/modules/5.4-gki.
+    std::sort(module_dirs.begin(), module_dirs.end());
+
+    for (const auto& module_dir : module_dirs) {
+        std::string dir_path = MODULE_BASE_DIR "/";
+        dir_path.append(module_dir);
+        Modprobe m({dir_path}, GetModuleLoadList(recovery, dir_path));
+        bool retval = m.LoadListedModules(!want_console);
+        int modules_loaded = m.GetModuleCount();
+        if (modules_loaded > 0) {
+            return retval;
+        }
+    }
+
+    Modprobe m({MODULE_BASE_DIR}, GetModuleLoadList(recovery, MODULE_BASE_DIR));
+    bool retval = m.LoadListedModules(!want_console);
+    int modules_loaded = m.GetModuleCount();
+    if (modules_loaded > 0) {
+        return retval;
+    }
+    return true;
+}
+
 int FirstStageMain(int argc, char** argv) {
     if (REBOOT_BOOTLOADER_ON_PANIC) {
         InstallRebootSignalHandlers();
@@ -190,18 +262,9 @@
         old_root_dir.reset();
     }
 
-    std::string module_load_file = "modules.load";
-    if (IsRecoveryMode() && !ForceNormalBoot(cmdline)) {
-        struct stat fileStat;
-        std::string recovery_load_path = "/lib/modules/modules.load.recovery";
-        if (!stat(recovery_load_path.c_str(), &fileStat)) {
-            module_load_file = "modules.load.recovery";
-        }
-    }
-
-    Modprobe m({"/lib/modules"}, module_load_file);
     auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline) : 0;
-    if (!m.LoadListedModules(!want_console)) {
+
+    if (!LoadKernelModules(IsRecoveryMode() && !ForceNormalBoot(cmdline), want_console)) {
         if (want_console != FirstStageConsoleParam::DISABLED) {
             LOG(ERROR) << "Failed to load kernel modules, starting console";
         } else {
diff --git a/libmodprobe/include/modprobe/modprobe.h b/libmodprobe/include/modprobe/modprobe.h
index 297036e..a7687af 100644
--- a/libmodprobe/include/modprobe/modprobe.h
+++ b/libmodprobe/include/modprobe/modprobe.h
@@ -34,6 +34,8 @@
     bool GetAllDependencies(const std::string& module, std::vector<std::string>* pre_dependencies,
                             std::vector<std::string>* dependencies,
                             std::vector<std::string>* post_dependencies);
+    void ResetModuleCount() { module_count_ = 0; }
+    int GetModuleCount() { return module_count_; }
     void EnableBlacklist(bool enable);
     void EnableVerbose(bool enable);
 
@@ -65,5 +67,6 @@
     std::unordered_map<std::string, std::string> module_options_;
     std::set<std::string> module_blacklist_;
     std::unordered_set<std::string> module_loaded_;
+    int module_count_ = 0;
     bool blacklist_enabled = false;
 };
diff --git a/libmodprobe/libmodprobe_ext.cpp b/libmodprobe/libmodprobe_ext.cpp
index 99472c1..6589708 100644
--- a/libmodprobe/libmodprobe_ext.cpp
+++ b/libmodprobe/libmodprobe_ext.cpp
@@ -63,6 +63,7 @@
 
     LOG(INFO) << "Loaded kernel module " << path_name;
     module_loaded_.emplace(canonical_name);
+    module_count_++;
     return true;
 }
 
diff --git a/libmodprobe/libmodprobe_ext_test.cpp b/libmodprobe/libmodprobe_ext_test.cpp
index 057dea3..9ee5ba7 100644
--- a/libmodprobe/libmodprobe_ext_test.cpp
+++ b/libmodprobe/libmodprobe_ext_test.cpp
@@ -56,6 +56,7 @@
     }
 
     modules_loaded.emplace_back(path_name + options);
+    module_count_++;
     return true;
 }
 
diff --git a/libmodprobe/libmodprobe_test.cpp b/libmodprobe/libmodprobe_test.cpp
index 879c7f2..eea0abd 100644
--- a/libmodprobe/libmodprobe_test.cpp
+++ b/libmodprobe/libmodprobe_test.cpp
@@ -161,6 +161,7 @@
 
     EXPECT_TRUE(modules_loaded == expected_modules_loaded);
 
+    EXPECT_TRUE(m.GetModuleCount() == 15);
     EXPECT_TRUE(m.Remove("test4"));
 
     GTEST_LOG_(INFO) << "Expected modules loaded after removing test4 (in order):";
diff --git a/logd/ChattyLogBuffer.cpp b/logd/ChattyLogBuffer.cpp
index c2e89fc..62c8629 100644
--- a/logd/ChattyLogBuffer.cpp
+++ b/logd/ChattyLogBuffer.cpp
@@ -74,7 +74,8 @@
     }
 
     // audit message (except sequence number) identical?
-    if (last.IsBinary() && lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) &&
+    if (IsBinary(last.log_id()) &&
+        lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) &&
         lenr > static_cast<ssize_t>(sizeof(android_log_event_string_t))) {
         if (fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_string_t) - sizeof(int32_t))) {
             return DIFFERENT;
@@ -205,9 +206,9 @@
 #endif
 
     if (coalesce) {
-        stats()->Erase(element);
+        stats()->Erase(element.ToLogStatisticsElement());
     } else {
-        stats()->Subtract(element);
+        stats()->Subtract(element.ToLogStatisticsElement());
     }
 
     it = SimpleLogBuffer::Erase(it);
@@ -533,7 +534,7 @@
             if (leading) {
                 it = Erase(it);
             } else {
-                stats()->Drop(element);
+                stats()->Drop(element.ToLogStatisticsElement());
                 element.SetDropped(1);
                 if (last.coalesce(&element, 1)) {
                     it = Erase(it, true);
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index 172a757..ef9f1cf 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -86,7 +86,7 @@
 
 uint32_t LogBufferElement::GetTag() const {
     // Binary buffers have no tag.
-    if (!IsBinary()) {
+    if (!IsBinary(log_id())) {
         return 0;
     }
 
@@ -95,12 +95,21 @@
         return tag_;
     }
 
-    // For non-dropped messages, we get the tag from the message header itself.
-    if (msg_len_ < sizeof(android_event_header_t)) {
-        return 0;
-    }
+    return MsgToTag(msg(), msg_len());
+}
 
-    return reinterpret_cast<const android_event_header_t*>(msg_)->tag;
+LogStatisticsElement LogBufferElement::ToLogStatisticsElement() const {
+    return LogStatisticsElement{
+            .uid = uid(),
+            .pid = pid(),
+            .tid = tid(),
+            .tag = GetTag(),
+            .realtime = realtime(),
+            .msg = msg(),
+            .msg_len = msg_len(),
+            .dropped_count = dropped_count(),
+            .log_id = log_id(),
+    };
 }
 
 uint16_t LogBufferElement::SetDropped(uint16_t value) {
@@ -218,7 +227,7 @@
                           type, dropped_count(), (dropped_count() > 1) ? "s" : "");
 
     size_t hdrLen;
-    if (IsBinary()) {
+    if (IsBinary(log_id())) {
         hdrLen = sizeof(android_log_event_string_t);
     } else {
         hdrLen = 1 + sizeof(tag);
@@ -232,7 +241,7 @@
     }
 
     size_t retval = hdrLen + len;
-    if (IsBinary()) {
+    if (IsBinary(log_id())) {
         android_log_event_string_t* event =
             reinterpret_cast<android_log_event_string_t*>(buffer);
 
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 5b13e32..fd5d88f 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -24,7 +24,7 @@
 
 #include "LogWriter.h"
 
-class LogStatistics;
+#include "LogStatistics.h"
 
 #define EXPIRE_HOUR_THRESHOLD 24  // Only expire chatty UID logs to preserve
                                   // non-chatty UIDs less than this age in hours
@@ -40,13 +40,13 @@
     LogBufferElement(LogBufferElement&& elem);
     ~LogBufferElement();
 
-    bool IsBinary() const { return (log_id_ == LOG_ID_EVENTS) || (log_id_ == LOG_ID_SECURITY); }
-
     uint32_t GetTag() const;
     uint16_t SetDropped(uint16_t value);
 
     bool FlushTo(LogWriter* writer, LogStatistics* parent, bool lastSame);
 
+    LogStatisticsElement ToLogStatisticsElement() const;
+
     log_id_t log_id() const { return static_cast<log_id_t>(log_id_); }
     uid_t uid() const { return uid_; }
     pid_t pid() const { return pid_; }
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index a2acab7..04fd59d 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -29,6 +29,8 @@
 
 #include <private/android_logger.h>
 
+#include "LogBufferElement.h"
+
 static const uint64_t hourSec = 60 * 60;
 static const uint64_t monthSec = 31 * 24 * hourSec;
 
@@ -87,10 +89,10 @@
     ++mElementsTotal[log_id];
 }
 
-void LogStatistics::Add(const LogBufferElement& element) {
+void LogStatistics::Add(const LogStatisticsElement& element) {
     auto lock = std::lock_guard{lock_};
-    log_id_t log_id = element.log_id();
-    uint16_t size = element.msg_len();
+    log_id_t log_id = element.log_id;
+    uint16_t size = element.msg_len;
     mSizes[log_id] += size;
     ++mElements[log_id];
 
@@ -99,7 +101,7 @@
     // evaluated and trimmed, thus recording size and number of
     // elements, but we must recognize the manufactured dropped
     // entry as not contributing to the lifetime totals.
-    if (element.dropped_count()) {
+    if (element.dropped_count) {
         ++mDroppedElements[log_id];
     } else {
         mSizesTotal[log_id] += size;
@@ -107,7 +109,7 @@
         ++mElementsTotal[log_id];
     }
 
-    log_time stamp(element.realtime());
+    log_time stamp(element.realtime);
     if (mNewest[log_id] < stamp) {
         // A major time update invalidates the statistics :-(
         log_time diff = stamp - mNewest[log_id];
@@ -132,19 +134,19 @@
         return;
     }
 
-    uidTable[log_id].Add(element.uid(), element);
-    if (element.uid() == AID_SYSTEM) {
-        pidSystemTable[log_id].Add(element.pid(), element);
+    uidTable[log_id].Add(element.uid, element);
+    if (element.uid == AID_SYSTEM) {
+        pidSystemTable[log_id].Add(element.pid, element);
     }
 
     if (!enable) {
         return;
     }
 
-    pidTable.Add(element.pid(), element);
-    tidTable.Add(element.tid(), element);
+    pidTable.Add(element.pid, element);
+    tidTable.Add(element.tid, element);
 
-    uint32_t tag = element.GetTag();
+    uint32_t tag = element.tag;
     if (tag) {
         if (log_id == LOG_ID_SECURITY) {
             securityTagTable.Add(tag, element);
@@ -153,42 +155,42 @@
         }
     }
 
-    if (!element.dropped_count()) {
+    if (!element.dropped_count) {
         tagNameTable.Add(TagNameKey(element), element);
     }
 }
 
-void LogStatistics::Subtract(const LogBufferElement& element) {
+void LogStatistics::Subtract(const LogStatisticsElement& element) {
     auto lock = std::lock_guard{lock_};
-    log_id_t log_id = element.log_id();
-    uint16_t size = element.msg_len();
+    log_id_t log_id = element.log_id;
+    uint16_t size = element.msg_len;
     mSizes[log_id] -= size;
     --mElements[log_id];
-    if (element.dropped_count()) {
+    if (element.dropped_count) {
         --mDroppedElements[log_id];
     }
 
-    if (mOldest[log_id] < element.realtime()) {
-        mOldest[log_id] = element.realtime();
+    if (mOldest[log_id] < element.realtime) {
+        mOldest[log_id] = element.realtime;
     }
 
     if (log_id == LOG_ID_KERNEL) {
         return;
     }
 
-    uidTable[log_id].Subtract(element.uid(), element);
-    if (element.uid() == AID_SYSTEM) {
-        pidSystemTable[log_id].Subtract(element.pid(), element);
+    uidTable[log_id].Subtract(element.uid, element);
+    if (element.uid == AID_SYSTEM) {
+        pidSystemTable[log_id].Subtract(element.pid, element);
     }
 
     if (!enable) {
         return;
     }
 
-    pidTable.Subtract(element.pid(), element);
-    tidTable.Subtract(element.tid(), element);
+    pidTable.Subtract(element.pid, element);
+    tidTable.Subtract(element.tid, element);
 
-    uint32_t tag = element.GetTag();
+    uint32_t tag = element.tag;
     if (tag) {
         if (log_id == LOG_ID_SECURITY) {
             securityTagTable.Subtract(tag, element);
@@ -197,37 +199,37 @@
         }
     }
 
-    if (!element.dropped_count()) {
+    if (!element.dropped_count) {
         tagNameTable.Subtract(TagNameKey(element), element);
     }
 }
 
 // Atomically set an entry to drop
 // entry->setDropped(1) must follow this call, caller should do this explicitly.
-void LogStatistics::Drop(const LogBufferElement& element) {
+void LogStatistics::Drop(const LogStatisticsElement& element) {
     auto lock = std::lock_guard{lock_};
-    log_id_t log_id = element.log_id();
-    uint16_t size = element.msg_len();
+    log_id_t log_id = element.log_id;
+    uint16_t size = element.msg_len;
     mSizes[log_id] -= size;
     ++mDroppedElements[log_id];
 
-    if (mNewestDropped[log_id] < element.realtime()) {
-        mNewestDropped[log_id] = element.realtime();
+    if (mNewestDropped[log_id] < element.realtime) {
+        mNewestDropped[log_id] = element.realtime;
     }
 
-    uidTable[log_id].Drop(element.uid(), element);
-    if (element.uid() == AID_SYSTEM) {
-        pidSystemTable[log_id].Drop(element.pid(), element);
+    uidTable[log_id].Drop(element.uid, element);
+    if (element.uid == AID_SYSTEM) {
+        pidSystemTable[log_id].Drop(element.pid, element);
     }
 
     if (!enable) {
         return;
     }
 
-    pidTable.Drop(element.pid(), element);
-    tidTable.Drop(element.tid(), element);
+    pidTable.Drop(element.pid, element);
+    tidTable.Drop(element.tid, element);
 
-    uint32_t tag = element.GetTag();
+    uint32_t tag = element.tag;
     if (tag) {
         if (log_id == LOG_ID_SECURITY) {
             securityTagTable.Drop(tag, element);
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 6a46adb..33a4d63 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -38,7 +38,6 @@
 #include <private/android_filesystem_config.h>
 #include <utils/FastStrcmp.h>
 
-#include "LogBufferElement.h"
 #include "LogUtils.h"
 
 #define log_id_for_each(i) \
@@ -46,6 +45,18 @@
 
 class LogStatistics;
 
+struct LogStatisticsElement {
+    uid_t uid;
+    pid_t pid;
+    pid_t tid;
+    uint32_t tag;
+    log_time realtime;
+    const char* msg;
+    uint16_t msg_len;
+    uint16_t dropped_count;
+    log_id_t log_id;
+};
+
 template <typename TKey, typename TEntry>
 class LogHashtable {
     std::unordered_map<TKey, TEntry> map;
@@ -113,7 +124,7 @@
         }
     }
 
-    iterator Add(const TKey& key, const LogBufferElement& element) {
+    iterator Add(const TKey& key, const LogStatisticsElement& element) {
         iterator it = map.find(key);
         if (it == map.end()) {
             it = map.insert(std::make_pair(key, TEntry(element))).first;
@@ -133,14 +144,14 @@
         return it;
     }
 
-    void Subtract(const TKey& key, const LogBufferElement& element) {
+    void Subtract(const TKey& key, const LogStatisticsElement& element) {
         iterator it = map.find(key);
         if (it != map.end() && it->second.Subtract(element)) {
             map.erase(it);
         }
     }
 
-    void Drop(const TKey& key, const LogBufferElement& element) {
+    void Drop(const TKey& key, const LogStatisticsElement& element) {
         iterator it = map.find(key);
         if (it != map.end()) {
             it->second.Drop(element);
@@ -156,13 +167,13 @@
 class EntryBase {
   public:
     EntryBase() : size_(0) {}
-    explicit EntryBase(const LogBufferElement& element) : size_(element.msg_len()) {}
+    explicit EntryBase(const LogStatisticsElement& element) : size_(element.msg_len) {}
 
     size_t getSizes() const { return size_; }
 
-    void Add(const LogBufferElement& element) { size_ += element.msg_len(); }
-    bool Subtract(const LogBufferElement& element) {
-        size_ -= element.msg_len();
+    void Add(const LogStatisticsElement& element) { size_ += element.msg_len; }
+    bool Subtract(const LogStatisticsElement& element) {
+        size_ -= element.msg_len;
         return !size_;
     }
 
@@ -193,20 +204,20 @@
 class EntryBaseDropped : public EntryBase {
   public:
     EntryBaseDropped() : dropped_(0) {}
-    explicit EntryBaseDropped(const LogBufferElement& element)
-        : EntryBase(element), dropped_(element.dropped_count()) {}
+    explicit EntryBaseDropped(const LogStatisticsElement& element)
+        : EntryBase(element), dropped_(element.dropped_count) {}
 
     size_t dropped_count() const { return dropped_; }
 
-    void Add(const LogBufferElement& element) {
-        dropped_ += element.dropped_count();
+    void Add(const LogStatisticsElement& element) {
+        dropped_ += element.dropped_count;
         EntryBase::Add(element);
     }
-    bool Subtract(const LogBufferElement& element) {
-        dropped_ -= element.dropped_count();
+    bool Subtract(const LogStatisticsElement& element) {
+        dropped_ -= element.dropped_count;
         return EntryBase::Subtract(element) && !dropped_;
     }
-    void Drop(const LogBufferElement& element) {
+    void Drop(const LogStatisticsElement& element) {
         dropped_ += 1;
         EntryBase::Subtract(element);
     }
@@ -217,15 +228,15 @@
 
 class UidEntry : public EntryBaseDropped {
   public:
-    explicit UidEntry(const LogBufferElement& element)
-        : EntryBaseDropped(element), uid_(element.uid()), pid_(element.pid()) {}
+    explicit UidEntry(const LogStatisticsElement& element)
+        : EntryBaseDropped(element), uid_(element.uid), pid_(element.pid) {}
 
     uid_t key() const { return uid_; }
     uid_t uid() const { return key(); }
     pid_t pid() const { return pid_; }
 
-    void Add(const LogBufferElement& element) {
-        if (pid_ != element.pid()) {
+    void Add(const LogStatisticsElement& element) {
+        if (pid_ != element.pid) {
             pid_ = -1;
         }
         EntryBaseDropped::Add(element);
@@ -250,10 +261,10 @@
           pid_(pid),
           uid_(android::pidToUid(pid)),
           name_(android::pidToName(pid)) {}
-    explicit PidEntry(const LogBufferElement& element)
+    explicit PidEntry(const LogStatisticsElement& element)
         : EntryBaseDropped(element),
-          pid_(element.pid()),
-          uid_(element.uid()),
+          pid_(element.pid),
+          uid_(element.uid),
           name_(android::pidToName(pid_)) {}
     PidEntry(const PidEntry& element)
         : EntryBaseDropped(element),
@@ -277,14 +288,14 @@
         }
     }
 
-    void Add(const LogBufferElement& element) {
-        uid_t incoming_uid = element.uid();
+    void Add(const LogStatisticsElement& element) {
+        uid_t incoming_uid = element.uid;
         if (uid() != incoming_uid) {
             uid_ = incoming_uid;
             free(name_);
-            name_ = android::pidToName(element.pid());
+            name_ = android::pidToName(element.pid);
         } else {
-            Add(element.pid());
+            Add(element.pid);
         }
         EntryBaseDropped::Add(element);
     }
@@ -306,11 +317,11 @@
           pid_(pid),
           uid_(android::pidToUid(tid)),
           name_(android::tidToName(tid)) {}
-    explicit TidEntry(const LogBufferElement& element)
+    explicit TidEntry(const LogStatisticsElement& element)
         : EntryBaseDropped(element),
-          tid_(element.tid()),
-          pid_(element.pid()),
-          uid_(element.uid()),
+          tid_(element.tid),
+          pid_(element.pid),
+          uid_(element.uid),
           name_(android::tidToName(tid_)) {}
     TidEntry(const TidEntry& element)
         : EntryBaseDropped(element),
@@ -336,16 +347,16 @@
         }
     }
 
-    void Add(const LogBufferElement& element) {
-        uid_t incoming_uid = element.uid();
-        pid_t incoming_pid = element.pid();
+    void Add(const LogStatisticsElement& element) {
+        uid_t incoming_uid = element.uid;
+        pid_t incoming_pid = element.pid;
         if (uid() != incoming_uid || pid() != incoming_pid) {
             uid_ = incoming_uid;
             pid_ = incoming_pid;
             free(name_);
-            name_ = android::tidToName(element.tid());
+            name_ = android::tidToName(element.tid);
         } else {
-            Add(element.tid());
+            Add(element.tid);
         }
         EntryBaseDropped::Add(element);
     }
@@ -362,22 +373,19 @@
 
 class TagEntry : public EntryBaseDropped {
   public:
-    explicit TagEntry(const LogBufferElement& element)
-        : EntryBaseDropped(element),
-          tag_(element.GetTag()),
-          pid_(element.pid()),
-          uid_(element.uid()) {}
+    explicit TagEntry(const LogStatisticsElement& element)
+        : EntryBaseDropped(element), tag_(element.tag), pid_(element.pid), uid_(element.uid) {}
 
     uint32_t key() const { return tag_; }
     pid_t pid() const { return pid_; }
     uid_t uid() const { return uid_; }
     const char* name() const { return android::tagToName(tag_); }
 
-    void Add(const LogBufferElement& element) {
-        if (uid_ != element.uid()) {
+    void Add(const LogStatisticsElement& element) {
+        if (uid_ != element.uid) {
             uid_ = -1;
         }
-        if (pid_ != element.pid()) {
+        if (pid_ != element.pid) {
             pid_ = -1;
         }
         EntryBaseDropped::Add(element);
@@ -396,9 +404,10 @@
     std::string* alloc;
     std::string_view name;  // Saves space if const char*
 
-    explicit TagNameKey(const LogBufferElement& element) : alloc(nullptr), name("", strlen("")) {
-        if (element.IsBinary()) {
-            uint32_t tag = element.GetTag();
+    explicit TagNameKey(const LogStatisticsElement& element)
+        : alloc(nullptr), name("", strlen("")) {
+        if (IsBinary(element.log_id)) {
+            uint32_t tag = element.tag;
             if (tag) {
                 const char* cp = android::tagToName(tag);
                 if (cp) {
@@ -412,13 +421,13 @@
             name = std::string_view(alloc->c_str(), alloc->size());
             return;
         }
-        const char* msg = element.msg();
+        const char* msg = element.msg;
         if (!msg) {
             name = std::string_view("chatty", strlen("chatty"));
             return;
         }
         ++msg;
-        uint16_t len = element.msg_len();
+        uint16_t len = element.msg_len;
         len = (len <= 1) ? 0 : strnlen(msg, len - 1);
         if (!len) {
             name = std::string_view("<NULL>", strlen("<NULL>"));
@@ -480,11 +489,11 @@
 
 class TagNameEntry : public EntryBase {
   public:
-    explicit TagNameEntry(const LogBufferElement& element)
+    explicit TagNameEntry(const LogStatisticsElement& element)
         : EntryBase(element),
-          tid_(element.tid()),
-          pid_(element.pid()),
-          uid_(element.uid()),
+          tid_(element.tid),
+          pid_(element.pid),
+          uid_(element.uid),
           name_(element) {}
 
     const TagNameKey& key() const { return name_; }
@@ -494,14 +503,14 @@
     const char* name() const { return name_.data(); }
     size_t getNameAllocLength() const { return name_.getAllocLength(); }
 
-    void Add(const LogBufferElement& element) {
-        if (uid_ != element.uid()) {
+    void Add(const LogStatisticsElement& element) {
+        if (uid_ != element.uid) {
             uid_ = -1;
         }
-        if (pid_ != element.pid()) {
+        if (pid_ != element.pid) {
             pid_ = -1;
         }
-        if (tid_ != element.tid()) {
+        if (tid_ != element.tid) {
             tid_ = -1;
         }
         EntryBase::Add(element);
@@ -590,14 +599,14 @@
     LogStatistics(bool enable_statistics);
 
     void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
-    void Add(const LogBufferElement& entry) EXCLUDES(lock_);
-    void Subtract(const LogBufferElement& entry) EXCLUDES(lock_);
+    void Add(const LogStatisticsElement& entry) EXCLUDES(lock_);
+    void Subtract(const LogStatisticsElement& entry) EXCLUDES(lock_);
     // entry->setDropped(1) must follow this call
-    void Drop(const LogBufferElement& entry) EXCLUDES(lock_);
+    void Drop(const LogStatisticsElement& entry) EXCLUDES(lock_);
     // Correct for coalescing two entries referencing dropped content
-    void Erase(const LogBufferElement& element) EXCLUDES(lock_) {
+    void Erase(const LogStatisticsElement& element) EXCLUDES(lock_) {
         auto lock = std::lock_guard{lock_};
-        log_id_t log_id = element.log_id();
+        log_id_t log_id = element.log_id;
         --mElements[log_id];
         --mDroppedElements[log_id];
     }
diff --git a/logd/LogUtils.h b/logd/LogUtils.h
index c472167..96aa1d3 100644
--- a/logd/LogUtils.h
+++ b/logd/LogUtils.h
@@ -60,6 +60,20 @@
 }
 }
 
+// Returns true if the log buffer is meant for binary logs.
+static inline bool IsBinary(log_id_t log_id) {
+    return log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS || log_id == LOG_ID_SECURITY;
+}
+
+// Returns the numeric log tag for binary log messages.
+static inline uint32_t MsgToTag(const char* msg, uint16_t msg_len) {
+    if (msg_len < sizeof(android_event_header_t)) {
+        return 0;
+    }
+
+    return reinterpret_cast<const android_event_header_t*>(msg)->tag;
+}
+
 static inline bool worstUidEnabledForLogid(log_id_t id) {
     return (id == LOG_ID_MAIN) || (id == LOG_ID_SYSTEM) ||
            (id == LOG_ID_RADIO) || (id == LOG_ID_EVENTS);
diff --git a/logd/SimpleLogBuffer.cpp b/logd/SimpleLogBuffer.cpp
index 5ab8e09..b4b3546 100644
--- a/logd/SimpleLogBuffer.cpp
+++ b/logd/SimpleLogBuffer.cpp
@@ -61,11 +61,8 @@
     int prio = ANDROID_LOG_INFO;
     const char* tag = nullptr;
     size_t tag_len = 0;
-    if (log_id == LOG_ID_EVENTS || log_id == LOG_ID_STATS) {
-        if (len < sizeof(android_event_header_t)) {
-            return false;
-        }
-        int32_t numeric_tag = reinterpret_cast<const android_event_header_t*>(msg)->tag;
+    if (IsBinary(log_id)) {
+        int32_t numeric_tag = MsgToTag(msg, len);
         tag = tags_->tagToName(numeric_tag);
         if (tag) {
             tag_len = strlen(tag);
@@ -105,7 +102,7 @@
     log_id_t log_id = elem.log_id();
 
     logs_.emplace_back(std::move(elem));
-    stats_->Add(logs_.back());
+    stats_->Add(logs_.back().ToLogStatisticsElement());
     MaybePrune(log_id);
     reader_list_->NotifyNewLog(1 << log_id);
 }
@@ -317,7 +314,7 @@
             return true;
         }
 
-        stats_->Subtract(element);
+        stats_->Subtract(element.ToLogStatisticsElement());
         it = Erase(it);
         if (--prune_rows == 0) {
             return false;