Merge "adb: don't use parameterized in test_adb.py."
diff --git a/fastboot/device/usb_client.cpp b/fastboot/device/usb_client.cpp
index 9c80765..c653167 100644
--- a/fastboot/device/usb_client.cpp
+++ b/fastboot/device/usb_client.cpp
@@ -146,7 +146,7 @@
},
};
-#define STR_INTERFACE_ "fastboot"
+#define STR_INTERFACE_ "fastbootd"
static const struct {
struct usb_functionfs_strings_head header;
diff --git a/fastboot/fastboot.cpp b/fastboot/fastboot.cpp
index 7f6e723..7abc936 100644
--- a/fastboot/fastboot.cpp
+++ b/fastboot/fastboot.cpp
@@ -258,6 +258,10 @@
static int list_devices_callback(usb_ifc_info* info) {
if (match_fastboot_with_serial(info, nullptr) == 0) {
std::string serial = info->serial_number;
+ std::string interface = info->interface;
+ if (interface.empty()) {
+ interface = "fastboot";
+ }
if (!info->writable) {
serial = UsbNoPermissionsShortHelpText();
}
@@ -266,9 +270,9 @@
}
// output compatible with "adb devices"
if (!g_long_listing) {
- printf("%s\tfastboot", serial.c_str());
+ printf("%s\t%s", serial.c_str(), interface.c_str());
} else {
- printf("%-22s fastboot", serial.c_str());
+ printf("%-22s %s", serial.c_str(), interface.c_str());
if (strlen(info->device_path) > 0) printf(" %s", info->device_path);
}
putchar('\n');
diff --git a/fastboot/usb.h b/fastboot/usb.h
index 7ca44c4..e5f56e2 100644
--- a/fastboot/usb.h
+++ b/fastboot/usb.h
@@ -50,6 +50,8 @@
char serial_number[256];
char device_path[256];
+
+ char interface[256];
};
class UsbTransport : public Transport {
diff --git a/fastboot/usb_linux.cpp b/fastboot/usb_linux.cpp
index 6363aa5..964488c 100644
--- a/fastboot/usb_linux.cpp
+++ b/fastboot/usb_linux.cpp
@@ -43,6 +43,8 @@
#include <linux/version.h>
#include <linux/usb/ch9.h>
+#include <android-base/file.h>
+#include <android-base/stringprintf.h>
#include <chrono>
#include <memory>
#include <thread>
@@ -263,6 +265,13 @@
info.has_bulk_in = (in != -1);
info.has_bulk_out = (out != -1);
+ std::string interface;
+ auto path = android::base::StringPrintf("/sys/bus/usb/devices/%s/%s:1.%d/interface",
+ sysfs_name, sysfs_name, ifc->bInterfaceNumber);
+ if (android::base::ReadFileToString(path, &interface)) {
+ snprintf(info.interface, sizeof(info.interface), "%s", interface.c_str());
+ }
+
if(callback(&info) == 0) {
*ept_in_id = in;
*ept_out_id = out;
diff --git a/fastboot/usb_osx.cpp b/fastboot/usb_osx.cpp
index 8a3c213..610eebf 100644
--- a/fastboot/usb_osx.cpp
+++ b/fastboot/usb_osx.cpp
@@ -368,6 +368,7 @@
// device has no serial number
handle->info.serial_number[0] = 0;
}
+ handle->info.interface[0] = 0;
handle->info.writable = 1;
if (try_interfaces(dev, handle)) {
diff --git a/fastboot/usb_windows.cpp b/fastboot/usb_windows.cpp
index bf840f8..67bf8a3 100644
--- a/fastboot/usb_windows.cpp
+++ b/fastboot/usb_windows.cpp
@@ -319,6 +319,7 @@
&serial_number_len, true)) {
info.serial_number[0] = 0;
}
+ info.interface[0] = 0;
info.device_path[0] = 0;
diff --git a/fs_mgr/libdm/dm.cpp b/fs_mgr/libdm/dm.cpp
index 673e145..7912688 100644
--- a/fs_mgr/libdm/dm.cpp
+++ b/fs_mgr/libdm/dm.cpp
@@ -29,6 +29,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/macros.h>
+#include <android-base/properties.h>
#include <android-base/strings.h>
#include <uuid/uuid.h>
@@ -140,6 +141,10 @@
return std::string{uuid_chars};
}
+static bool IsRecovery() {
+ return access("/system/bin/recovery", F_OK) == 0;
+}
+
bool DeviceMapper::CreateDevice(const std::string& name, const DmTable& table, std::string* path,
const std::chrono::milliseconds& timeout_ms) {
std::string uuid = GenerateUuid();
@@ -160,6 +165,16 @@
if (timeout_ms <= std::chrono::milliseconds::zero()) {
return true;
}
+
+ if (IsRecovery()) {
+ bool non_ab_device = android::base::GetProperty("ro.build.ab_update", "").empty();
+ int sdk = android::base::GetIntProperty("ro.build.version.sdk", 0);
+ if (non_ab_device && sdk && sdk <= 29) {
+ LOG(INFO) << "Detected ueventd incompatibility, reverting to legacy libdm behavior.";
+ unique_path = *path;
+ }
+ }
+
if (!WaitForFile(unique_path, timeout_ms)) {
LOG(ERROR) << "Failed waiting for device path: " << unique_path;
DeleteDevice(name);
diff --git a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
index 2ac0c44..0328132 100644
--- a/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+++ b/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
@@ -132,7 +132,7 @@
uint64 metadata_sectors = 4;
}
-// Next: 2
+// Next: 4
message SnapshotMergeReport {
// Status of the update after the merge attempts.
UpdateState state = 1;
@@ -140,4 +140,7 @@
// Number of reboots that occurred after issuing and before completeing the
// merge of all the snapshot devices.
int32 resume_count = 2;
+
+ // Total size of all the COW images before the update.
+ uint64 cow_file_size = 3;
}
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
index cf0b085..4457de3 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/mock_snapshot.h
@@ -25,7 +25,7 @@
MOCK_METHOD(bool, BeginUpdate, (), (override));
MOCK_METHOD(bool, CancelUpdate, (), (override));
MOCK_METHOD(bool, FinishedSnapshotWrites, (bool wipe), (override));
- MOCK_METHOD(bool, InitiateMerge, (), (override));
+ MOCK_METHOD(bool, InitiateMerge, (uint64_t * cow_file_size), (override));
MOCK_METHOD(UpdateState, ProcessUpdateState,
(const std::function<bool()>& callback, const std::function<bool()>& before_cancel),
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
index 2d6071f..3c2c776 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot.h
@@ -124,7 +124,7 @@
// Initiate a merge on all snapshot devices. This should only be used after an
// update has been marked successful after booting.
- virtual bool InitiateMerge() = 0;
+ virtual bool InitiateMerge(uint64_t* cow_file_size = nullptr) = 0;
// Perform any necessary post-boot actions. This should be run soon after
// /data is mounted.
@@ -281,7 +281,7 @@
bool BeginUpdate() override;
bool CancelUpdate() override;
bool FinishedSnapshotWrites(bool wipe) override;
- bool InitiateMerge() override;
+ bool InitiateMerge(uint64_t* cow_file_size = nullptr) override;
UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
const std::function<bool()>& before_cancel = {}) override;
UpdateState GetUpdateState(double* progress = nullptr) override;
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
index 4caf632..d691d4f 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stats.h
@@ -29,6 +29,8 @@
// Called when merge starts or resumes.
virtual bool Start() = 0;
virtual void set_state(android::snapshot::UpdateState state) = 0;
+ virtual void set_cow_file_size(uint64_t cow_file_size) = 0;
+ virtual uint64_t cow_file_size() = 0;
// Called when merge ends. Properly clean up permanent storage.
class Result {
@@ -50,6 +52,8 @@
// ISnapshotMergeStats overrides
bool Start() override;
void set_state(android::snapshot::UpdateState state) override;
+ void set_cow_file_size(uint64_t cow_file_size) override;
+ uint64_t cow_file_size() override;
std::unique_ptr<Result> Finish() override;
private:
diff --git a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
index 9c82906..7a27fad 100644
--- a/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
+++ b/fs_mgr/libsnapshot/include/libsnapshot/snapshot_stub.h
@@ -27,7 +27,7 @@
bool BeginUpdate() override;
bool CancelUpdate() override;
bool FinishedSnapshotWrites(bool wipe) override;
- bool InitiateMerge() override;
+ bool InitiateMerge(uint64_t* cow_file_size = nullptr) override;
UpdateState ProcessUpdateState(const std::function<bool()>& callback = {},
const std::function<bool()>& before_cancel = {}) override;
UpdateState GetUpdateState(double* progress = nullptr) override;
diff --git a/fs_mgr/libsnapshot/snapshot.cpp b/fs_mgr/libsnapshot/snapshot.cpp
index 488009a..5909cff 100644
--- a/fs_mgr/libsnapshot/snapshot.cpp
+++ b/fs_mgr/libsnapshot/snapshot.cpp
@@ -555,7 +555,7 @@
return true;
}
-bool SnapshotManager::InitiateMerge() {
+bool SnapshotManager::InitiateMerge(uint64_t* cow_file_size) {
auto lock = LockExclusive();
if (!lock) return false;
@@ -618,6 +618,7 @@
}
}
+ uint64_t total_cow_file_size = 0;
DmTargetSnapshot::Status initial_target_values = {};
for (const auto& snapshot : snapshots) {
DmTargetSnapshot::Status current_status;
@@ -627,6 +628,16 @@
initial_target_values.sectors_allocated += current_status.sectors_allocated;
initial_target_values.total_sectors += current_status.total_sectors;
initial_target_values.metadata_sectors += current_status.metadata_sectors;
+
+ SnapshotStatus snapshot_status;
+ if (!ReadSnapshotStatus(lock.get(), snapshot, &snapshot_status)) {
+ return false;
+ }
+ total_cow_file_size += snapshot_status.cow_file_size();
+ }
+
+ if (cow_file_size) {
+ *cow_file_size = total_cow_file_size;
}
SnapshotUpdateStatus initial_status;
diff --git a/fs_mgr/libsnapshot/snapshot_stats.cpp b/fs_mgr/libsnapshot/snapshot_stats.cpp
index 5da7b98..3723730 100644
--- a/fs_mgr/libsnapshot/snapshot_stats.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stats.cpp
@@ -88,6 +88,15 @@
report_.set_state(state);
}
+void SnapshotMergeStats::set_cow_file_size(uint64_t cow_file_size) {
+ report_.set_cow_file_size(cow_file_size);
+ WriteState();
+}
+
+uint64_t SnapshotMergeStats::cow_file_size() {
+ return report_.cow_file_size();
+}
+
class SnapshotMergeStatsResultImpl : public SnapshotMergeStats::Result {
public:
SnapshotMergeStatsResultImpl(const SnapshotMergeReport& report,
diff --git a/fs_mgr/libsnapshot/snapshot_stub.cpp b/fs_mgr/libsnapshot/snapshot_stub.cpp
index 2aaa78c..9b6f758 100644
--- a/fs_mgr/libsnapshot/snapshot_stub.cpp
+++ b/fs_mgr/libsnapshot/snapshot_stub.cpp
@@ -42,7 +42,7 @@
return false;
}
-bool SnapshotManagerStub::InitiateMerge() {
+bool SnapshotManagerStub::InitiateMerge(uint64_t*) {
LOG(ERROR) << __FUNCTION__ << " should never be called.";
return false;
}
@@ -118,6 +118,8 @@
class SnapshotMergeStatsStub : public ISnapshotMergeStats {
bool Start() override { return false; }
void set_state(android::snapshot::UpdateState) override {}
+ void set_cow_file_size(uint64_t) override {}
+ uint64_t cow_file_size() override { return 0; }
std::unique_ptr<Result> Finish() override { return nullptr; }
};
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 0f7044a..ea39d34 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -246,6 +246,7 @@
"String8_test.cpp",
"String16_test.cpp",
"StrongPointer_test.cpp",
+ "Timers_test.cpp",
"Unicode_test.cpp",
"Vector_test.cpp",
],
diff --git a/libutils/Timers.cpp b/libutils/Timers.cpp
index 1172ae7..fd3f4a9 100644
--- a/libutils/Timers.cpp
+++ b/libutils/Timers.cpp
@@ -20,31 +20,37 @@
#include <utils/Timers.h>
#include <limits.h>
+#include <stdlib.h>
#include <time.h>
-// host linux support requires Linux 2.6.39+
+#include <android-base/macros.h>
+
+static constexpr size_t clock_id_max = 5;
+
+static void checkClockId(int clock) {
+ if (clock < 0 || clock >= clock_id_max) abort();
+}
+
#if defined(__linux__)
-nsecs_t systemTime(int clock)
-{
- static const clockid_t clocks[] = {
- CLOCK_REALTIME,
- CLOCK_MONOTONIC,
- CLOCK_PROCESS_CPUTIME_ID,
- CLOCK_THREAD_CPUTIME_ID,
- CLOCK_BOOTTIME
- };
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
+nsecs_t systemTime(int clock) {
+ checkClockId(clock);
+ static constexpr clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC,
+ CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID,
+ CLOCK_BOOTTIME};
+ static_assert(clock_id_max == arraysize(clocks));
+ timespec t = {};
clock_gettime(clocks[clock], &t);
return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
}
#else
-nsecs_t systemTime(int /*clock*/)
-{
+nsecs_t systemTime(int clock) {
+ // TODO: is this ever called with anything but REALTIME on mac/windows?
+ checkClockId(clock);
+
// Clock support varies widely across hosts. Mac OS doesn't support
- // CLOCK_BOOTTIME, and Windows is windows.
- struct timeval t;
- t.tv_sec = t.tv_usec = 0;
+ // CLOCK_BOOTTIME (and doesn't even have clock_gettime until 10.12).
+ // Windows is windows.
+ timeval t = {};
gettimeofday(&t, nullptr);
return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL;
}
diff --git a/libutils/Timers_test.cpp b/libutils/Timers_test.cpp
new file mode 100644
index 0000000..ec0051e
--- /dev/null
+++ b/libutils/Timers_test.cpp
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utils/Timers.h>
+
+#include <gtest/gtest.h>
+
+TEST(Timers, systemTime_invalid) {
+ EXPECT_EXIT(systemTime(-1), testing::KilledBySignal(SIGABRT), "");
+ systemTime(SYSTEM_TIME_REALTIME);
+ systemTime(SYSTEM_TIME_MONOTONIC);
+ systemTime(SYSTEM_TIME_PROCESS);
+ systemTime(SYSTEM_TIME_THREAD);
+ systemTime(SYSTEM_TIME_BOOTTIME);
+ EXPECT_EXIT(systemTime(SYSTEM_TIME_BOOTTIME + 1), testing::KilledBySignal(SIGABRT), "");
+}
diff --git a/libutils/include/utils/Timers.h b/libutils/include/utils/Timers.h
index 54ec474..197fc26 100644
--- a/libutils/include/utils/Timers.h
+++ b/libutils/include/utils/Timers.h
@@ -14,11 +14,7 @@
* limitations under the License.
*/
-//
-// Timer functions.
-//
-#ifndef _LIBS_UTILS_TIMERS_H
-#define _LIBS_UTILS_TIMERS_H
+#pragma once
#include <stdint.h>
#include <sys/types.h>
@@ -77,11 +73,11 @@
static CONSTEXPR inline nsecs_t microseconds(nsecs_t v) { return us2ns(v); }
enum {
- SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock
- SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
- SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock
- SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock
- SYSTEM_TIME_BOOTTIME = 4 // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
+ SYSTEM_TIME_REALTIME = 0, // system-wide realtime clock
+ SYSTEM_TIME_MONOTONIC = 1, // monotonic time since unspecified starting point
+ SYSTEM_TIME_PROCESS = 2, // high-resolution per-process clock
+ SYSTEM_TIME_THREAD = 3, // high-resolution per-thread clock
+ SYSTEM_TIME_BOOTTIME = 4, // same as SYSTEM_TIME_MONOTONIC, but including CPU suspend time
};
// return the system-time according to the specified clock
@@ -104,5 +100,3 @@
#ifdef __cplusplus
} // extern "C"
#endif
-
-#endif // _LIBS_UTILS_TIMERS_H
diff --git a/logd/ChattyLogBuffer.cpp b/logd/ChattyLogBuffer.cpp
index 0ba6025..c2e89fc 100644
--- a/logd/ChattyLogBuffer.cpp
+++ b/logd/ChattyLogBuffer.cpp
@@ -48,38 +48,33 @@
enum match_type { DIFFERENT, SAME, SAME_LIBLOG };
-static enum match_type Identical(LogBufferElement* elem, LogBufferElement* last) {
- // is it mostly identical?
- // if (!elem) return DIFFERENT;
- ssize_t lenl = elem->getMsgLen();
+static enum match_type Identical(const LogBufferElement& elem, const LogBufferElement& last) {
+ ssize_t lenl = elem.msg_len();
if (lenl <= 0) return DIFFERENT; // value if this represents a chatty elem
- // if (!last) return DIFFERENT;
- ssize_t lenr = last->getMsgLen();
+ ssize_t lenr = last.msg_len();
if (lenr <= 0) return DIFFERENT; // value if this represents a chatty elem
- // if (elem->getLogId() != last->getLogId()) return DIFFERENT;
- if (elem->getUid() != last->getUid()) return DIFFERENT;
- if (elem->getPid() != last->getPid()) return DIFFERENT;
- if (elem->getTid() != last->getTid()) return DIFFERENT;
+ if (elem.uid() != last.uid()) return DIFFERENT;
+ if (elem.pid() != last.pid()) return DIFFERENT;
+ if (elem.tid() != last.tid()) return DIFFERENT;
// last is more than a minute old, stop squashing identical messages
- if (elem->getRealTime().nsec() > (last->getRealTime().nsec() + 60 * NS_PER_SEC))
- return DIFFERENT;
+ if (elem.realtime().nsec() > (last.realtime().nsec() + 60 * NS_PER_SEC)) return DIFFERENT;
// Identical message
- const char* msgl = elem->getMsg();
- const char* msgr = last->getMsg();
+ const char* msgl = elem.msg();
+ const char* msgr = last.msg();
if (lenl == lenr) {
if (!fastcmp<memcmp>(msgl, msgr, lenl)) return SAME;
// liblog tagged messages (content gets summed)
- if (elem->getLogId() == LOG_ID_EVENTS && lenl == sizeof(android_log_event_int_t) &&
+ if (elem.log_id() == LOG_ID_EVENTS && lenl == sizeof(android_log_event_int_t) &&
!fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_int_t) - sizeof(int32_t)) &&
- elem->getTag() == LIBLOG_LOG_TAG) {
+ elem.GetTag() == LIBLOG_LOG_TAG) {
return SAME_LIBLOG;
}
}
// audit message (except sequence number) identical?
- if (last->isBinary() && lenl > static_cast<ssize_t>(sizeof(android_log_event_string_t)) &&
+ if (last.IsBinary() && 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;
@@ -105,11 +100,11 @@
void ChattyLogBuffer::LogInternal(LogBufferElement&& elem) {
// b/137093665: don't coalesce security messages.
- if (elem.getLogId() == LOG_ID_SECURITY) {
+ if (elem.log_id() == LOG_ID_SECURITY) {
SimpleLogBuffer::LogInternal(std::move(elem));
return;
}
- int log_id = elem.getLogId();
+ int log_id = elem.log_id();
// Initialize last_logged_elements_ to a copy of elem if logging the first element for a log_id.
if (!last_logged_elements_[log_id]) {
@@ -119,12 +114,12 @@
}
LogBufferElement& current_last = *last_logged_elements_[log_id];
- enum match_type match = Identical(&elem, ¤t_last);
+ enum match_type match = Identical(elem, current_last);
if (match == DIFFERENT) {
if (duplicate_elements_[log_id]) {
// If we previously had 3+ identical messages, log the chatty message.
- if (duplicate_elements_[log_id]->getDropped() > 0) {
+ if (duplicate_elements_[log_id]->dropped_count() > 0) {
SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id]));
}
duplicate_elements_[log_id].reset();
@@ -146,10 +141,10 @@
// 3+ identical LIBLOG event messages: coalesce them into last_logged_elements_.
if (match == SAME_LIBLOG) {
const android_log_event_int_t* current_last_event =
- reinterpret_cast<const android_log_event_int_t*>(current_last.getMsg());
+ reinterpret_cast<const android_log_event_int_t*>(current_last.msg());
int64_t current_last_count = current_last_event->payload.data;
android_log_event_int_t* elem_event =
- reinterpret_cast<android_log_event_int_t*>(const_cast<char*>(elem.getMsg()));
+ reinterpret_cast<android_log_event_int_t*>(const_cast<char*>(elem.msg()));
int64_t elem_count = elem_event->payload.data;
int64_t total = current_last_count + elem_count;
@@ -158,22 +153,22 @@
last_logged_elements_[log_id].emplace(std::move(elem));
return;
}
- stats()->AddTotal(current_last.getLogId(), current_last.getMsgLen());
+ stats()->AddTotal(current_last.log_id(), current_last.msg_len());
elem_event->payload.data = total;
last_logged_elements_[log_id].emplace(std::move(elem));
return;
}
// 3+ identical messages (not LIBLOG) messages: increase the drop count.
- uint16_t dropped_count = duplicate_elements_[log_id]->getDropped();
+ uint16_t dropped_count = duplicate_elements_[log_id]->dropped_count();
if (dropped_count == std::numeric_limits<uint16_t>::max()) {
SimpleLogBuffer::LogInternal(std::move(*duplicate_elements_[log_id]));
dropped_count = 0;
}
// We're dropping the current_last log so add its stats to the total.
- stats()->AddTotal(current_last.getLogId(), current_last.getMsgLen());
+ stats()->AddTotal(current_last.log_id(), current_last.msg_len());
// Use current_last for tracking the dropped count to always use the latest timestamp.
- current_last.setDropped(dropped_count + 1);
+ current_last.SetDropped(dropped_count + 1);
duplicate_elements_[log_id].emplace(std::move(current_last));
last_logged_elements_[log_id].emplace(std::move(elem));
}
@@ -181,14 +176,13 @@
LogBufferElementCollection::iterator ChattyLogBuffer::Erase(LogBufferElementCollection::iterator it,
bool coalesce) {
LogBufferElement& element = *it;
- log_id_t id = element.getLogId();
+ log_id_t id = element.log_id();
// Remove iterator references in the various lists that will become stale
// after the element is erased from the main logging list.
{ // start of scope for found iterator
- int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.getTag()
- : element.getUid();
+ int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.GetTag() : element.uid();
LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
if ((found != mLastWorst[id].end()) && (it == found->second)) {
mLastWorst[id].erase(found);
@@ -196,10 +190,10 @@
}
{ // start of scope for pid found iterator
- // element->getUid() may not be AID_SYSTEM for next-best-watermark.
+ // element->uid() may not be AID_SYSTEM for next-best-watermark.
// will not assume id != LOG_ID_EVENTS or LOG_ID_SECURITY for KISS and
// long term code stability, find() check should be fast for those ids.
- LogBufferPidIteratorMap::iterator found = mLastWorstPidOfSystem[id].find(element.getPid());
+ LogBufferPidIteratorMap::iterator found = mLastWorstPidOfSystem[id].find(element.pid());
if (found != mLastWorstPidOfSystem[id].end() && it == found->second) {
mLastWorstPidOfSystem[id].erase(found);
}
@@ -207,14 +201,13 @@
#ifdef DEBUG_CHECK_FOR_STALE_ENTRIES
LogBufferElementCollection::iterator bad = it;
- int key =
- (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element->getTag() : element->getUid();
+ int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element->GetTag() : element->uid();
#endif
if (coalesce) {
- stats()->Erase(&element);
+ stats()->Erase(element);
} else {
- stats()->Subtract(&element);
+ stats()->Subtract(element);
}
it = SimpleLogBuffer::Erase(it);
@@ -245,15 +238,15 @@
public:
bool coalesce(LogBufferElement* element, uint16_t dropped) {
- uint64_t key = LogBufferElementKey(element->getUid(), element->getPid(), element->getTid());
+ uint64_t key = LogBufferElementKey(element->uid(), element->pid(), element->tid());
LogBufferElementMap::iterator it = map.find(key);
if (it != map.end()) {
LogBufferElement* found = it->second;
- uint16_t moreDropped = found->getDropped();
+ uint16_t moreDropped = found->dropped_count();
if ((dropped + moreDropped) > USHRT_MAX) {
map.erase(it);
} else {
- found->setDropped(dropped + moreDropped);
+ found->SetDropped(dropped + moreDropped);
return true;
}
}
@@ -261,18 +254,18 @@
}
void add(LogBufferElement* element) {
- uint64_t key = LogBufferElementKey(element->getUid(), element->getPid(), element->getTid());
+ uint64_t key = LogBufferElementKey(element->uid(), element->pid(), element->tid());
map[key] = element;
}
void clear() { map.clear(); }
void clear(LogBufferElement* element) {
- uint64_t current = element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
+ uint64_t current = element->realtime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
for (LogBufferElementMap::iterator it = map.begin(); it != map.end();) {
LogBufferElement* mapElement = it->second;
- if (mapElement->getDropped() >= EXPIRE_THRESHOLD &&
- current > mapElement->getRealTime().nsec()) {
+ if (mapElement->dropped_count() >= EXPIRE_THRESHOLD &&
+ current > mapElement->realtime().nsec()) {
it = map.erase(it);
} else {
++it;
@@ -359,12 +352,12 @@
while (it != logs().end()) {
LogBufferElement& element = *it;
- if (element.getLogId() != id || element.getUid() != caller_uid) {
+ if (element.log_id() != id || element.uid() != caller_uid) {
++it;
continue;
}
- if (oldest && oldest->start() <= element.getSequence()) {
+ if (oldest && oldest->start() <= element.sequence()) {
busy = true;
KickReader(oldest, id, pruneRows);
break;
@@ -382,7 +375,7 @@
bool hasBlacklist = (id != LOG_ID_SECURITY) && prune_->naughty();
while (!clearAll && (pruneRows > 0)) {
// recalculate the worst offender on every batched pass
- int worst = -1; // not valid for getUid() or getKey()
+ int worst = -1; // not valid for uid() or getKey()
size_t worst_sizes = 0;
size_t second_worst_sizes = 0;
pid_t worstPid = 0; // POSIX guarantees PID != 0
@@ -445,19 +438,19 @@
while (it != logs().end()) {
LogBufferElement& element = *it;
- if (oldest && oldest->start() <= element.getSequence()) {
+ if (oldest && oldest->start() <= element.sequence()) {
busy = true;
// Do not let chatty eliding trigger any reader mitigation
break;
}
- if (element.getLogId() != id) {
+ if (element.log_id() != id) {
++it;
continue;
}
- // below this point element->getLogId() == id
+ // below this point element->log_id() == id
- uint16_t dropped = element.getDropped();
+ uint16_t dropped = element.dropped_count();
// remove any leading drops
if (leading && dropped) {
@@ -470,8 +463,8 @@
continue;
}
- int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.getTag()
- : element.getUid();
+ int key = (id == LOG_ID_EVENTS || id == LOG_ID_SECURITY) ? element.GetTag()
+ : element.uid();
if (hasBlacklist && prune_->naughty(&element)) {
last.clear(&element);
@@ -490,25 +483,25 @@
if (worst_sizes < second_worst_sizes) {
break;
}
- worst_sizes -= element.getMsgLen();
+ worst_sizes -= element.msg_len();
}
continue;
}
- if (element.getRealTime() < (lastt->getRealTime() - too_old) ||
- element.getRealTime() > lastt->getRealTime()) {
+ if (element.realtime() < (lastt->realtime() - too_old) ||
+ element.realtime() > lastt->realtime()) {
break;
}
if (dropped) {
last.add(&element);
- if (worstPid && ((!gc && element.getPid() == worstPid) ||
- mLastWorstPidOfSystem[id].find(element.getPid()) ==
+ if (worstPid && ((!gc && element.pid() == worstPid) ||
+ mLastWorstPidOfSystem[id].find(element.pid()) ==
mLastWorstPidOfSystem[id].end())) {
- // element->getUid() may not be AID_SYSTEM, next best
+ // element->uid() may not be AID_SYSTEM, next best
// watermark if current one empty. id is not LOG_ID_EVENTS
// or LOG_ID_SECURITY because of worstPid check.
- mLastWorstPidOfSystem[id][element.getPid()] = it;
+ mLastWorstPidOfSystem[id][element.pid()] = it;
}
if ((!gc && !worstPid && (key == worst)) ||
(mLastWorst[id].find(key) == mLastWorst[id].end())) {
@@ -518,14 +511,14 @@
continue;
}
- if (key != worst || (worstPid && element.getPid() != worstPid)) {
+ if (key != worst || (worstPid && element.pid() != worstPid)) {
leading = false;
last.clear(&element);
++it;
continue;
}
// key == worst below here
- // If worstPid set, then element->getPid() == worstPid below here
+ // If worstPid set, then element->pid() == worstPid below here
pruneRows--;
if (pruneRows == 0) {
@@ -534,21 +527,21 @@
kick = true;
- uint16_t len = element.getMsgLen();
+ uint16_t len = element.msg_len();
// do not create any leading drops
if (leading) {
it = Erase(it);
} else {
- stats()->Drop(&element);
- element.setDropped(1);
+ stats()->Drop(element);
+ element.SetDropped(1);
if (last.coalesce(&element, 1)) {
it = Erase(it, true);
} else {
last.add(&element);
if (worstPid && (!gc || mLastWorstPidOfSystem[id].find(worstPid) ==
mLastWorstPidOfSystem[id].end())) {
- // element->getUid() may not be AID_SYSTEM, next best
+ // element->uid() may not be AID_SYSTEM, next best
// watermark if current one empty. id is not
// LOG_ID_EVENTS or LOG_ID_SECURITY because of worstPid.
mLastWorstPidOfSystem[id][worstPid] = it;
@@ -577,18 +570,18 @@
while ((pruneRows > 0) && (it != logs().end())) {
LogBufferElement& element = *it;
- if (element.getLogId() != id) {
+ if (element.log_id() != id) {
it++;
continue;
}
- if (oldest && oldest->start() <= element.getSequence()) {
+ if (oldest && oldest->start() <= element.sequence()) {
busy = true;
if (!whitelist) KickReader(oldest, id, pruneRows);
break;
}
- if (hasWhitelist && !element.getDropped() && prune_->nice(&element)) {
+ if (hasWhitelist && !element.dropped_count() && prune_->nice(&element)) {
// WhiteListed
whitelist = true;
it++;
@@ -605,12 +598,12 @@
while ((it != logs().end()) && (pruneRows > 0)) {
LogBufferElement& element = *it;
- if (element.getLogId() != id) {
+ if (element.log_id() != id) {
++it;
continue;
}
- if (oldest && oldest->start() <= element.getSequence()) {
+ if (oldest && oldest->start() <= element.sequence()) {
busy = true;
KickReader(oldest, id, pruneRows);
break;
diff --git a/logd/ChattyLogBufferTest.cpp b/logd/ChattyLogBufferTest.cpp
index 2e0c947..8754b88 100644
--- a/logd/ChattyLogBufferTest.cpp
+++ b/logd/ChattyLogBufferTest.cpp
@@ -61,7 +61,8 @@
std::vector<LogMessage> read_log_messages;
std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
- log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
+ std::unique_ptr<FlushToState> flush_to_state = log_buffer_->CreateFlushToState(1, kLogMaskAll);
+ EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr));
std::vector<LogMessage> expected_log_messages = {
make_message(0, "test_tag", "duplicate"),
@@ -72,12 +73,12 @@
make_message(5, "test_tag", "not_same"),
// 3 duplicate logs together print the first, a 1 count chatty message, then the last.
make_message(6, "test_tag", "duplicate"),
- make_message(7, "chatty", "uid=0\\([^\\)]+\\) [^ ]+ expire 1 line", true),
+ make_message(7, "chatty", "uid=0\\([^\\)]+\\) [^ ]+ identical 1 line", true),
make_message(8, "test_tag", "duplicate"),
make_message(9, "test_tag", "not_same"),
// 6 duplicate logs together print the first, a 4 count chatty message, then the last.
make_message(10, "test_tag", "duplicate"),
- make_message(14, "chatty", "uid=0\\([^\\)]+\\) [^ ]+ expire 4 lines", true),
+ make_message(14, "chatty", "uid=0\\([^\\)]+\\) [^ ]+ identical 4 lines", true),
make_message(15, "test_tag", "duplicate"),
make_message(16, "test_tag", "not_same"),
// duplicate logs > 1 minute apart are not deduplicated.
@@ -117,15 +118,16 @@
std::vector<LogMessage> read_log_messages;
std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
- log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
+ std::unique_ptr<FlushToState> flush_to_state = log_buffer_->CreateFlushToState(1, kLogMaskAll);
+ EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr));
std::vector<LogMessage> expected_log_messages = {
make_message(0, "test_tag", "normal"),
make_message(1, "test_tag", "duplicate"),
make_message(expired_per_chatty_message + 1, "chatty",
- "uid=0\\([^\\)]+\\) [^ ]+ expire 65535 lines", true),
+ "uid=0\\([^\\)]+\\) [^ ]+ identical 65535 lines", true),
make_message(expired_per_chatty_message + 2, "chatty",
- "uid=0\\([^\\)]+\\) [^ ]+ expire 1 line", true),
+ "uid=0\\([^\\)]+\\) [^ ]+ identical 1 line", true),
make_message(expired_per_chatty_message + 3, "test_tag", "duplicate"),
make_message(expired_per_chatty_message + 4, "test_tag", "normal"),
};
@@ -172,7 +174,8 @@
std::vector<LogMessage> read_log_messages;
std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
- log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
+ std::unique_ptr<FlushToState> flush_to_state = log_buffer_->CreateFlushToState(1, kLogMaskAll);
+ EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr));
std::vector<LogMessage> expected_log_messages = {
make_message(0, 1234, 1),
@@ -199,4 +202,4 @@
CompareLogMessages(expected_log_messages, read_log_messages);
};
-INSTANTIATE_TEST_CASE_P(ChattyLogBufferTests, ChattyLogBufferTest, testing::Values("chatty"));
\ No newline at end of file
+INSTANTIATE_TEST_CASE_P(ChattyLogBufferTests, ChattyLogBufferTest, testing::Values("chatty"));
diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h
index 7f1e128..a3ac683 100644
--- a/logd/LogBuffer.h
+++ b/logd/LogBuffer.h
@@ -21,13 +21,32 @@
#include <functional>
#include <log/log.h>
-#include <sysutils/SocketClient.h>
+#include <log/log_read.h>
-#include "LogBufferElement.h"
+#include "LogWriter.h"
-class LogWriter;
+// A mask to represent which log buffers a reader is watching, values are (1 << LOG_ID_MAIN), etc.
+using LogMask = uint32_t;
+constexpr uint32_t kLogMaskAll = 0xFFFFFFFF;
-enum class FlushToResult {
+// State that a LogBuffer may want to persist across calls to FlushTo().
+class FlushToState {
+ public:
+ FlushToState(uint64_t start, LogMask log_mask) : start_(start), log_mask_(log_mask) {}
+ virtual ~FlushToState() {}
+
+ uint64_t start() const { return start_; }
+ void set_start(uint64_t start) { start_ = start; }
+
+ LogMask log_mask() const { return log_mask_; }
+
+ private:
+ uint64_t start_;
+ LogMask log_mask_;
+};
+
+// Enum for the return values of the `filter` function passed to FlushTo().
+enum class FilterResult {
kSkip,
kStop,
kWrite,
@@ -41,18 +60,16 @@
virtual int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
const char* msg, uint16_t len) = 0;
- // lastTid is an optional context to help detect if the last previous
- // valid message was from the same source so we can differentiate chatty
- // filter types (identical or expired)
- static const uint64_t FLUSH_ERROR = 0;
- virtual uint64_t FlushTo(
- LogWriter* writer, uint64_t start,
- pid_t* last_tid, // nullable
- const std::function<FlushToResult(const LogBufferElement* element)>& filter) = 0;
+
+ virtual std::unique_ptr<FlushToState> CreateFlushToState(uint64_t start, LogMask log_mask) = 0;
+ virtual bool FlushTo(LogWriter* writer, FlushToState& state,
+ const std::function<FilterResult(log_id_t log_id, pid_t pid,
+ uint64_t sequence, log_time realtime,
+ uint16_t dropped_count)>& filter) = 0;
virtual bool Clear(log_id_t id, uid_t uid) = 0;
virtual unsigned long GetSize(log_id_t id) = 0;
virtual int SetSize(log_id_t id, unsigned long size) = 0;
virtual uint64_t sequence() const = 0;
-};
\ No newline at end of file
+};
diff --git a/logd/LogBufferElement.cpp b/logd/LogBufferElement.cpp
index c6dbda8..172a757 100644
--- a/logd/LogBufferElement.cpp
+++ b/logd/LogBufferElement.cpp
@@ -32,92 +32,92 @@
LogBufferElement::LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
pid_t tid, uint64_t sequence, const char* msg, uint16_t len)
- : mUid(uid),
- mPid(pid),
- mTid(tid),
- mSequence(sequence),
- mRealTime(realtime),
- mMsgLen(len),
- mLogId(log_id),
- mDropped(false) {
- mMsg = new char[len];
- memcpy(mMsg, msg, len);
+ : uid_(uid),
+ pid_(pid),
+ tid_(tid),
+ sequence_(sequence),
+ realtime_(realtime),
+ msg_len_(len),
+ log_id_(log_id),
+ dropped_(false) {
+ msg_ = new char[len];
+ memcpy(msg_, msg, len);
}
LogBufferElement::LogBufferElement(const LogBufferElement& elem)
- : mUid(elem.mUid),
- mPid(elem.mPid),
- mTid(elem.mTid),
- mSequence(elem.mSequence),
- mRealTime(elem.mRealTime),
- mMsgLen(elem.mMsgLen),
- mLogId(elem.mLogId),
- mDropped(elem.mDropped) {
- if (mDropped) {
- mTag = elem.getTag();
+ : uid_(elem.uid_),
+ pid_(elem.pid_),
+ tid_(elem.tid_),
+ sequence_(elem.sequence_),
+ realtime_(elem.realtime_),
+ msg_len_(elem.msg_len_),
+ log_id_(elem.log_id_),
+ dropped_(elem.dropped_) {
+ if (dropped_) {
+ tag_ = elem.GetTag();
} else {
- mMsg = new char[mMsgLen];
- memcpy(mMsg, elem.mMsg, mMsgLen);
+ msg_ = new char[msg_len_];
+ memcpy(msg_, elem.msg_, msg_len_);
}
}
LogBufferElement::LogBufferElement(LogBufferElement&& elem)
- : mUid(elem.mUid),
- mPid(elem.mPid),
- mTid(elem.mTid),
- mSequence(elem.mSequence),
- mRealTime(elem.mRealTime),
- mMsgLen(elem.mMsgLen),
- mLogId(elem.mLogId),
- mDropped(elem.mDropped) {
- if (mDropped) {
- mTag = elem.getTag();
+ : uid_(elem.uid_),
+ pid_(elem.pid_),
+ tid_(elem.tid_),
+ sequence_(elem.sequence_),
+ realtime_(elem.realtime_),
+ msg_len_(elem.msg_len_),
+ log_id_(elem.log_id_),
+ dropped_(elem.dropped_) {
+ if (dropped_) {
+ tag_ = elem.GetTag();
} else {
- mMsg = elem.mMsg;
- elem.mMsg = nullptr;
+ msg_ = elem.msg_;
+ elem.msg_ = nullptr;
}
}
LogBufferElement::~LogBufferElement() {
- if (!mDropped) {
- delete[] mMsg;
+ if (!dropped_) {
+ delete[] msg_;
}
}
-uint32_t LogBufferElement::getTag() const {
+uint32_t LogBufferElement::GetTag() const {
// Binary buffers have no tag.
- if (!isBinary()) {
+ if (!IsBinary()) {
return 0;
}
- // Dropped messages store the tag in place of mMsg.
- if (mDropped) {
- return mTag;
+ // Dropped messages store the tag in place of msg_.
+ if (dropped_) {
+ return tag_;
}
// For non-dropped messages, we get the tag from the message header itself.
- if (mMsgLen < sizeof(android_event_header_t)) {
+ if (msg_len_ < sizeof(android_event_header_t)) {
return 0;
}
- return reinterpret_cast<const android_event_header_t*>(mMsg)->tag;
+ return reinterpret_cast<const android_event_header_t*>(msg_)->tag;
}
-uint16_t LogBufferElement::setDropped(uint16_t value) {
- if (mDropped) {
- return mDroppedCount = value;
+uint16_t LogBufferElement::SetDropped(uint16_t value) {
+ if (dropped_) {
+ return dropped_count_ = value;
}
- // The tag information is saved in mMsg data, which is in a union with mTag, used after mDropped
- // is set to true. Therefore we save the tag value aside, delete mMsg, then set mTag to the tag
+ // The tag information is saved in msg_ data, which is in a union with tag_, used after dropped_
+ // is set to true. Therefore we save the tag value aside, delete msg_, then set tag_ to the tag
// value in its place.
- auto old_tag = getTag();
- delete[] mMsg;
- mMsg = nullptr;
+ auto old_tag = GetTag();
+ delete[] msg_;
+ msg_ = nullptr;
- mTag = old_tag;
- mDropped = true;
- return mDroppedCount = value;
+ tag_ = old_tag;
+ dropped_ = true;
+ return dropped_count_ = value;
}
// caller must own and free character string
@@ -165,8 +165,8 @@
return retval;
}
-// assumption: mMsg == NULL
-size_t LogBufferElement::populateDroppedMessage(char*& buffer, LogStatistics* stats,
+// assumption: msg_ == NULL
+size_t LogBufferElement::PopulateDroppedMessage(char*& buffer, LogStatistics* stats,
bool lastSame) {
static const char tag[] = "chatty";
@@ -176,13 +176,13 @@
}
static const char format_uid[] = "uid=%u%s%s %s %u line%s";
- const char* name = stats->UidToName(mUid);
- const char* commName = android::tidToName(mTid);
- if (!commName && (mTid != mPid)) {
- commName = android::tidToName(mPid);
+ const char* name = stats->UidToName(uid_);
+ const char* commName = android::tidToName(tid_);
+ if (!commName && (tid_ != pid_)) {
+ commName = android::tidToName(pid_);
}
if (!commName) {
- commName = stats->PidToName(mPid);
+ commName = stats->PidToName(pid_);
}
if (name && name[0] && commName && (name[0] == commName[0])) {
size_t len = strlen(name + 1);
@@ -214,12 +214,11 @@
}
// identical to below to calculate the buffer size required
const char* type = lastSame ? "identical" : "expire";
- size_t len = snprintf(nullptr, 0, format_uid, mUid, name ? name : "",
- commName ? commName : "", type, getDropped(),
- (getDropped() > 1) ? "s" : "");
+ size_t len = snprintf(nullptr, 0, format_uid, uid_, name ? name : "", commName ? commName : "",
+ type, dropped_count(), (dropped_count() > 1) ? "s" : "");
size_t hdrLen;
- if (isBinary()) {
+ if (IsBinary()) {
hdrLen = sizeof(android_log_event_string_t);
} else {
hdrLen = 1 + sizeof(tag);
@@ -233,7 +232,7 @@
}
size_t retval = hdrLen + len;
- if (isBinary()) {
+ if (IsBinary()) {
android_log_event_string_t* event =
reinterpret_cast<android_log_event_string_t*>(buffer);
@@ -246,9 +245,8 @@
strcpy(buffer + 1, tag);
}
- snprintf(buffer + hdrLen, len + 1, format_uid, mUid, name ? name : "",
- commName ? commName : "", type, getDropped(),
- (getDropped() > 1) ? "s" : "");
+ snprintf(buffer + hdrLen, len + 1, format_uid, uid_, name ? name : "", commName ? commName : "",
+ type, dropped_count(), (dropped_count() > 1) ? "s" : "");
free(const_cast<char*>(name));
free(const_cast<char*>(commName));
@@ -259,22 +257,22 @@
struct logger_entry entry = {};
entry.hdr_size = sizeof(struct logger_entry);
- entry.lid = mLogId;
- entry.pid = mPid;
- entry.tid = mTid;
- entry.uid = mUid;
- entry.sec = mRealTime.tv_sec;
- entry.nsec = mRealTime.tv_nsec;
+ entry.lid = log_id_;
+ entry.pid = pid_;
+ entry.tid = tid_;
+ entry.uid = uid_;
+ entry.sec = realtime_.tv_sec;
+ entry.nsec = realtime_.tv_nsec;
char* buffer = nullptr;
const char* msg;
- if (mDropped) {
- entry.len = populateDroppedMessage(buffer, stats, lastSame);
+ if (dropped_) {
+ entry.len = PopulateDroppedMessage(buffer, stats, lastSame);
if (!entry.len) return true;
msg = buffer;
} else {
- msg = mMsg;
- entry.len = mMsgLen;
+ msg = msg_;
+ entry.len = msg_len_;
}
bool retval = writer->Write(entry, msg);
diff --git a/logd/LogBufferElement.h b/logd/LogBufferElement.h
index 35252f9..5b13e32 100644
--- a/logd/LogBufferElement.h
+++ b/logd/LogBufferElement.h
@@ -33,26 +33,6 @@
#define EXPIRE_RATELIMIT 10 // maximum rate in seconds to report expiration
class __attribute__((packed)) LogBufferElement {
- // sized to match reality of incoming log packets
- const uint32_t mUid;
- const uint32_t mPid;
- const uint32_t mTid;
- uint64_t mSequence;
- log_time mRealTime;
- union {
- char* mMsg; // mDropped == false
- int32_t mTag; // mDropped == true
- };
- union {
- const uint16_t mMsgLen; // mDropped == false
- uint16_t mDroppedCount; // mDropped == true
- };
- const uint8_t mLogId;
- bool mDropped;
-
- // assumption: mDropped == true
- size_t populateDroppedMessage(char*& buffer, LogStatistics* parent, bool lastSame);
-
public:
LogBufferElement(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
uint64_t sequence, const char* msg, uint16_t len);
@@ -60,37 +40,41 @@
LogBufferElement(LogBufferElement&& elem);
~LogBufferElement();
- bool isBinary(void) const {
- return (mLogId == LOG_ID_EVENTS) || (mLogId == LOG_ID_SECURITY);
- }
+ bool IsBinary() const { return (log_id_ == LOG_ID_EVENTS) || (log_id_ == LOG_ID_SECURITY); }
- log_id_t getLogId() const {
- return static_cast<log_id_t>(mLogId);
- }
- uid_t getUid(void) const {
- return mUid;
- }
- pid_t getPid(void) const {
- return mPid;
- }
- pid_t getTid(void) const {
- return mTid;
- }
- uint32_t getTag() const;
- uint16_t getDropped(void) const {
- return mDropped ? mDroppedCount : 0;
- }
- uint16_t setDropped(uint16_t value);
- uint16_t getMsgLen() const {
- return mDropped ? 0 : mMsgLen;
- }
- const char* getMsg() const {
- return mDropped ? nullptr : mMsg;
- }
- uint64_t getSequence() const { return mSequence; }
- log_time getRealTime(void) const {
- return mRealTime;
- }
+ uint32_t GetTag() const;
+ uint16_t SetDropped(uint16_t value);
bool FlushTo(LogWriter* writer, LogStatistics* parent, bool lastSame);
+
+ 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_; }
+ pid_t tid() const { return tid_; }
+ uint16_t msg_len() const { return dropped_ ? 0 : msg_len_; }
+ const char* msg() const { return dropped_ ? nullptr : msg_; }
+ uint64_t sequence() const { return sequence_; }
+ log_time realtime() const { return realtime_; }
+ uint16_t dropped_count() const { return dropped_ ? dropped_count_ : 0; }
+
+ private:
+ // assumption: mDropped == true
+ size_t PopulateDroppedMessage(char*& buffer, LogStatistics* parent, bool lastSame);
+
+ // sized to match reality of incoming log packets
+ const uint32_t uid_;
+ const uint32_t pid_;
+ const uint32_t tid_;
+ uint64_t sequence_;
+ log_time realtime_;
+ union {
+ char* msg_; // mDropped == false
+ int32_t tag_; // mDropped == true
+ };
+ union {
+ const uint16_t msg_len_; // mDropped == false
+ uint16_t dropped_count_; // mDropped == true
+ };
+ const uint8_t log_id_;
+ bool dropped_;
};
diff --git a/logd/LogBufferTest.cpp b/logd/LogBufferTest.cpp
index 334d57b..bc01c80 100644
--- a/logd/LogBufferTest.cpp
+++ b/logd/LogBufferTest.cpp
@@ -208,8 +208,9 @@
std::vector<LogMessage> read_log_messages;
std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, nullptr));
- uint64_t flush_result = log_buffer_->FlushTo(test_writer.get(), 1, nullptr, nullptr);
- EXPECT_EQ(1ULL, flush_result);
+ std::unique_ptr<FlushToState> flush_to_state = log_buffer_->CreateFlushToState(1, kLogMaskAll);
+ EXPECT_TRUE(log_buffer_->FlushTo(test_writer.get(), *flush_to_state, nullptr));
+ EXPECT_EQ(2ULL, flush_to_state->start());
CompareLogMessages(log_messages, read_log_messages);
}
@@ -335,4 +336,39 @@
CompareLogMessages(log_messages, read_log_messages);
}
+TEST_P(LogBufferTest, read_last_sequence) {
+ std::vector<LogMessage> log_messages = {
+ {{.pid = 1, .tid = 2, .sec = 10000, .nsec = 20001, .lid = LOG_ID_MAIN, .uid = 0},
+ "first"},
+ {{.pid = 10, .tid = 2, .sec = 10000, .nsec = 20002, .lid = LOG_ID_MAIN, .uid = 0},
+ "second"},
+ {{.pid = 100, .tid = 2, .sec = 10000, .nsec = 20003, .lid = LOG_ID_MAIN, .uid = 0},
+ "third"},
+ };
+ FixupMessages(&log_messages);
+ LogMessages(log_messages);
+
+ std::vector<LogMessage> read_log_messages;
+ bool released = false;
+
+ {
+ auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
+ std::unique_ptr<LogWriter> test_writer(new TestWriter(&read_log_messages, &released));
+ std::unique_ptr<LogReaderThread> log_reader(
+ new LogReaderThread(log_buffer_.get(), &reader_list_, std::move(test_writer), true,
+ 0, ~0, 0, {}, 3, {}));
+ reader_list_.reader_threads().emplace_back(std::move(log_reader));
+ }
+
+ while (!released) {
+ usleep(5000);
+ }
+ {
+ auto lock = std::unique_lock{reader_list_.reader_threads_lock()};
+ EXPECT_EQ(0U, reader_list_.reader_threads().size());
+ }
+ std::vector<LogMessage> expected_log_messages = {log_messages.back()};
+ CompareLogMessages(expected_log_messages, read_log_messages);
+}
+
INSTANTIATE_TEST_CASE_P(LogBufferTests, LogBufferTest, testing::Values("chatty", "simple"));
diff --git a/logd/LogBufferTest.h b/logd/LogBufferTest.h
index 1659f12..f91a1b5 100644
--- a/logd/LogBufferTest.h
+++ b/logd/LogBufferTest.h
@@ -45,7 +45,7 @@
class TestWriter : public LogWriter {
public:
TestWriter(std::vector<LogMessage>* msgs, bool* released)
- : LogWriter(0, true, true), msgs_(msgs), released_(released) {}
+ : LogWriter(0, true), msgs_(msgs), released_(released) {}
bool Write(const logger_entry& entry, const char* message) override {
msgs_->emplace_back(LogMessage{entry, std::string(message, entry.len), false});
return true;
diff --git a/logd/LogReader.cpp b/logd/LogReader.cpp
index 234ddc7..44bafb9 100644
--- a/logd/LogReader.cpp
+++ b/logd/LogReader.cpp
@@ -45,11 +45,8 @@
class SocketLogWriter : public LogWriter {
public:
- SocketLogWriter(LogReader* reader, SocketClient* client, bool privileged,
- bool can_read_security_logs)
- : LogWriter(client->getUid(), privileged, can_read_security_logs),
- reader_(reader),
- client_(client) {}
+ SocketLogWriter(LogReader* reader, SocketClient* client, bool privileged)
+ : LogWriter(client->getUid(), privileged), reader_(reader), client_(client) {}
bool Write(const logger_entry& entry, const char* msg) override {
struct iovec iovec[2];
@@ -162,39 +159,39 @@
bool privileged = clientHasLogCredentials(cli);
bool can_read_security = CanReadSecurityLogs(cli);
+ if (!can_read_security) {
+ logMask &= ~(1 << LOG_ID_SECURITY);
+ }
- std::unique_ptr<LogWriter> socket_log_writer(
- new SocketLogWriter(this, cli, privileged, can_read_security));
+ std::unique_ptr<LogWriter> socket_log_writer(new SocketLogWriter(this, cli, privileged));
uint64_t sequence = 1;
// Convert realtime to sequence number
if (start != log_time::EPOCH) {
bool start_time_set = false;
uint64_t last = sequence;
- auto log_find_start = [pid, logMask, start, &sequence, &start_time_set,
- &last](const LogBufferElement* element) -> FlushToResult {
- if (pid && pid != element->getPid()) {
- return FlushToResult::kSkip;
+ auto log_find_start = [pid, start, &sequence, &start_time_set, &last](
+ log_id_t, pid_t element_pid, uint64_t element_sequence,
+ log_time element_realtime, uint16_t) -> FilterResult {
+ if (pid && pid != element_pid) {
+ return FilterResult::kSkip;
}
- if ((logMask & (1 << element->getLogId())) == 0) {
- return FlushToResult::kSkip;
- }
- if (start == element->getRealTime()) {
- sequence = element->getSequence();
+ if (start == element_realtime) {
+ sequence = element_sequence;
start_time_set = true;
- return FlushToResult::kStop;
+ return FilterResult::kStop;
} else {
- if (start < element->getRealTime()) {
+ if (start < element_realtime) {
sequence = last;
start_time_set = true;
- return FlushToResult::kStop;
+ return FilterResult::kStop;
}
- last = element->getSequence();
+ last = element_sequence;
}
- return FlushToResult::kSkip;
+ return FilterResult::kSkip;
};
-
- log_buffer_->FlushTo(socket_log_writer.get(), sequence, nullptr, log_find_start);
+ auto flush_to_state = log_buffer_->CreateFlushToState(sequence, logMask);
+ log_buffer_->FlushTo(socket_log_writer.get(), *flush_to_state, log_find_start);
if (!start_time_set) {
if (nonBlock) {
diff --git a/logd/LogReaderList.cpp b/logd/LogReaderList.cpp
index 220027b..32ba291 100644
--- a/logd/LogReaderList.cpp
+++ b/logd/LogReaderList.cpp
@@ -18,7 +18,7 @@
// When we are notified a new log entry is available, inform
// listening sockets who are watching this entry's log id.
-void LogReaderList::NotifyNewLog(unsigned int log_mask) const {
+void LogReaderList::NotifyNewLog(LogMask log_mask) const {
auto lock = std::lock_guard{reader_threads_lock_};
for (const auto& entry : reader_threads_) {
diff --git a/logd/LogReaderList.h b/logd/LogReaderList.h
index 0d84aba..594716a 100644
--- a/logd/LogReaderList.h
+++ b/logd/LogReaderList.h
@@ -20,11 +20,12 @@
#include <memory>
#include <mutex>
+#include "LogBuffer.h"
#include "LogReaderThread.h"
class LogReaderList {
public:
- void NotifyNewLog(unsigned int log_mask) const;
+ void NotifyNewLog(LogMask log_mask) const;
std::list<std::unique_ptr<LogReaderThread>>& reader_threads() { return reader_threads_; }
std::mutex& reader_threads_lock() { return reader_threads_lock_; }
diff --git a/logd/LogReaderThread.cpp b/logd/LogReaderThread.cpp
index b2001b5..c6e60fe 100644
--- a/logd/LogReaderThread.cpp
+++ b/logd/LogReaderThread.cpp
@@ -29,24 +29,22 @@
LogReaderThread::LogReaderThread(LogBuffer* log_buffer, LogReaderList* reader_list,
std::unique_ptr<LogWriter> writer, bool non_block,
- unsigned long tail, unsigned int log_mask, pid_t pid,
+ unsigned long tail, LogMask log_mask, pid_t pid,
log_time start_time, uint64_t start,
std::chrono::steady_clock::time_point deadline)
: log_buffer_(log_buffer),
reader_list_(reader_list),
writer_(std::move(writer)),
leading_dropped_(false),
- log_mask_(log_mask),
pid_(pid),
tail_(tail),
count_(0),
index_(0),
start_time_(start_time),
- start_(start),
deadline_(deadline),
non_block_(non_block) {
- memset(last_tid_, 0, sizeof(last_tid_));
cleanSkip_Locked();
+ flush_to_state_ = log_buffer_->CreateFlushToState(start, log_mask);
auto thread = std::thread{&LogReaderThread::ThreadFunction, this};
thread.detach();
}
@@ -58,8 +56,6 @@
auto lock = std::unique_lock{reader_list_->reader_threads_lock()};
- uint64_t start = start_;
-
while (!release_) {
if (deadline_.time_since_epoch().count() != 0) {
if (thread_triggered_condition_.wait_until(lock, deadline_) ==
@@ -74,14 +70,24 @@
lock.unlock();
if (tail_) {
- log_buffer_->FlushTo(writer_.get(), start, nullptr,
- std::bind(&LogReaderThread::FilterFirstPass, this, _1));
+ auto first_pass_state = log_buffer_->CreateFlushToState(flush_to_state_->start(),
+ flush_to_state_->log_mask());
+ log_buffer_->FlushTo(writer_.get(), *first_pass_state,
+ [this](log_id_t log_id, pid_t pid, uint64_t sequence,
+ log_time realtime, uint16_t dropped_count) {
+ return FilterFirstPass(log_id, pid, sequence, realtime,
+ dropped_count);
+ });
leading_dropped_ =
true; // TODO: Likely a bug, if leading_dropped_ was not true before calling
// flushTo(), then it should not be reset to true after.
}
- start = log_buffer_->FlushTo(writer_.get(), start, last_tid_,
- std::bind(&LogReaderThread::FilterSecondPass, this, _1));
+ bool flush_success = log_buffer_->FlushTo(
+ writer_.get(), *flush_to_state_,
+ [this](log_id_t log_id, pid_t pid, uint64_t sequence, log_time realtime,
+ uint16_t dropped_count) {
+ return FilterSecondPass(log_id, pid, sequence, realtime, dropped_count);
+ });
// We only ignore entries before the original start time for the first flushTo(), if we
// get entries after this first flush before the original start time, then the client
@@ -94,12 +100,10 @@
lock.lock();
- if (start == LogBuffer::FLUSH_ERROR) {
+ if (!flush_success) {
break;
}
- start_ = start + 1;
-
if (non_block_ || release_) {
break;
}
@@ -123,65 +127,56 @@
}
// A first pass to count the number of elements
-FlushToResult LogReaderThread::FilterFirstPass(const LogBufferElement* element) {
+FilterResult LogReaderThread::FilterFirstPass(log_id_t, pid_t pid, uint64_t, log_time realtime,
+ uint16_t dropped_count) {
auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
if (leading_dropped_) {
- if (element->getDropped()) {
- return FlushToResult::kSkip;
+ if (dropped_count) {
+ return FilterResult::kSkip;
}
leading_dropped_ = false;
}
- if (count_ == 0) {
- start_ = element->getSequence();
- }
-
- if ((!pid_ || pid_ == element->getPid()) && IsWatching(element->getLogId()) &&
- (start_time_ == log_time::EPOCH || start_time_ <= element->getRealTime())) {
+ if ((!pid_ || pid_ == pid) && (start_time_ == log_time::EPOCH || start_time_ <= realtime)) {
++count_;
}
- return FlushToResult::kSkip;
+ return FilterResult::kSkip;
}
// A second pass to send the selected elements
-FlushToResult LogReaderThread::FilterSecondPass(const LogBufferElement* element) {
+FilterResult LogReaderThread::FilterSecondPass(log_id_t log_id, pid_t pid, uint64_t,
+ log_time realtime, uint16_t dropped_count) {
auto lock = std::lock_guard{reader_list_->reader_threads_lock()};
- start_ = element->getSequence();
-
- if (skip_ahead_[element->getLogId()]) {
- skip_ahead_[element->getLogId()]--;
- return FlushToResult::kSkip;
+ if (skip_ahead_[log_id]) {
+ skip_ahead_[log_id]--;
+ return FilterResult::kSkip;
}
if (leading_dropped_) {
- if (element->getDropped()) {
- return FlushToResult::kSkip;
+ if (dropped_count) {
+ return FilterResult::kSkip;
}
leading_dropped_ = false;
}
// Truncate to close race between first and second pass
if (non_block_ && tail_ && index_ >= count_) {
- return FlushToResult::kStop;
+ return FilterResult::kStop;
}
- if (!IsWatching(element->getLogId())) {
- return FlushToResult::kSkip;
+ if (pid_ && pid_ != pid) {
+ return FilterResult::kSkip;
}
- if (pid_ && pid_ != element->getPid()) {
- return FlushToResult::kSkip;
- }
-
- if (start_time_ != log_time::EPOCH && element->getRealTime() <= start_time_) {
- return FlushToResult::kSkip;
+ if (start_time_ != log_time::EPOCH && realtime <= start_time_) {
+ return FilterResult::kSkip;
}
if (release_) {
- return FlushToResult::kStop;
+ return FilterResult::kStop;
}
if (!tail_) {
@@ -191,7 +186,7 @@
++index_;
if (count_ > tail_ && index_ <= (count_ - tail_)) {
- return FlushToResult::kSkip;
+ return FilterResult::kSkip;
}
if (!non_block_) {
@@ -199,10 +194,10 @@
}
ok:
- if (!skip_ahead_[element->getLogId()]) {
- return FlushToResult::kWrite;
+ if (!skip_ahead_[log_id]) {
+ return FilterResult::kWrite;
}
- return FlushToResult::kSkip;
+ return FilterResult::kSkip;
}
void LogReaderThread::cleanSkip_Locked(void) {
diff --git a/logd/LogReaderThread.h b/logd/LogReaderThread.h
index e48a3ca..f288d68 100644
--- a/logd/LogReaderThread.h
+++ b/logd/LogReaderThread.h
@@ -30,7 +30,6 @@
#include <sysutils/SocketClient.h>
#include "LogBuffer.h"
-#include "LogBufferElement.h"
#include "LogWriter.h"
class LogReaderList;
@@ -39,7 +38,7 @@
public:
LogReaderThread(LogBuffer* log_buffer, LogReaderList* reader_list,
std::unique_ptr<LogWriter> writer, bool non_block, unsigned long tail,
- unsigned int log_mask, pid_t pid, log_time start_time, uint64_t sequence,
+ LogMask log_mask, pid_t pid, log_time start_time, uint64_t sequence,
std::chrono::steady_clock::time_point deadline);
void triggerReader_Locked() { thread_triggered_condition_.notify_all(); }
@@ -53,18 +52,22 @@
thread_triggered_condition_.notify_all();
}
- bool IsWatching(log_id_t id) const { return log_mask_ & (1 << id); }
- bool IsWatchingMultiple(unsigned int log_mask) const { return log_mask_ & log_mask; }
+ bool IsWatching(log_id_t id) const { return flush_to_state_->log_mask() & (1 << id); }
+ bool IsWatchingMultiple(LogMask log_mask) const {
+ return flush_to_state_->log_mask() & log_mask;
+ }
std::string name() const { return writer_->name(); }
- uint64_t start() const { return start_; }
+ uint64_t start() const { return flush_to_state_->start(); }
std::chrono::steady_clock::time_point deadline() const { return deadline_; }
private:
void ThreadFunction();
// flushTo filter callbacks
- FlushToResult FilterFirstPass(const LogBufferElement* element);
- FlushToResult FilterSecondPass(const LogBufferElement* element);
+ FilterResult FilterFirstPass(log_id_t log_id, pid_t pid, uint64_t sequence, log_time realtime,
+ uint16_t dropped_count);
+ FilterResult FilterSecondPass(log_id_t log_id, pid_t pid, uint64_t sequence, log_time realtime,
+ uint16_t dropped_count);
std::condition_variable thread_triggered_condition_;
LogBuffer* log_buffer_;
@@ -77,16 +80,14 @@
// messages should be ignored.
bool leading_dropped_;
- // A mask of the logs buffers that are read by this reader.
- const unsigned int log_mask_;
// If set to non-zero, only pids equal to this are read by the reader.
const pid_t pid_;
// When a reader is referencing (via start_) old elements in the log buffer, and the log
// buffer's size grows past its memory limit, the log buffer may request the reader to skip
// ahead a specified number of logs.
unsigned int skip_ahead_[LOG_ID_MAX];
- // Used for distinguishing 'dropped' messages for duplicate logs vs chatty drops
- pid_t last_tid_[LOG_ID_MAX];
+ // LogBuffer::FlushTo() needs to store state across subsequent calls.
+ std::unique_ptr<FlushToState> flush_to_state_;
// These next three variables are used for reading only the most recent lines aka `adb logcat
// -t` / `adb logcat -T`.
@@ -102,8 +103,6 @@
// When a reader requests logs starting from a given timestamp, its stored here for the first
// pass, such that logs before this time stamp that are accumulated in the buffer are ignored.
log_time start_time_;
- // The point from which the reader will read logs once awoken.
- uint64_t start_;
// CLOCK_MONOTONIC based deadline used for log wrapping. If this deadline expires before logs
// wrap, then wake up and send the logs to the reader anyway.
std::chrono::steady_clock::time_point deadline_;
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index bb7621d..a2acab7 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -87,10 +87,10 @@
++mElementsTotal[log_id];
}
-void LogStatistics::Add(LogBufferElement* element) {
+void LogStatistics::Add(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element->getLogId();
- uint16_t size = element->getMsgLen();
+ log_id_t log_id = element.log_id();
+ uint16_t size = element.msg_len();
mSizes[log_id] += size;
++mElements[log_id];
@@ -99,7 +99,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->getDropped()) {
+ if (element.dropped_count()) {
++mDroppedElements[log_id];
} else {
mSizesTotal[log_id] += size;
@@ -107,7 +107,7 @@
++mElementsTotal[log_id];
}
- log_time stamp(element->getRealTime());
+ 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,111 +132,111 @@
return;
}
- uidTable[log_id].add(element->getUid(), element);
- if (element->getUid() == AID_SYSTEM) {
- pidSystemTable[log_id].add(element->getPid(), 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->getPid(), element);
- tidTable.add(element->getTid(), element);
+ pidTable.Add(element.pid(), element);
+ tidTable.Add(element.tid(), element);
- uint32_t tag = element->getTag();
+ uint32_t tag = element.GetTag();
if (tag) {
if (log_id == LOG_ID_SECURITY) {
- securityTagTable.add(tag, element);
+ securityTagTable.Add(tag, element);
} else {
- tagTable.add(tag, element);
+ tagTable.Add(tag, element);
}
}
- if (!element->getDropped()) {
- tagNameTable.add(TagNameKey(element), element);
+ if (!element.dropped_count()) {
+ tagNameTable.Add(TagNameKey(element), element);
}
}
-void LogStatistics::Subtract(LogBufferElement* element) {
+void LogStatistics::Subtract(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element->getLogId();
- uint16_t size = element->getMsgLen();
+ log_id_t log_id = element.log_id();
+ uint16_t size = element.msg_len();
mSizes[log_id] -= size;
--mElements[log_id];
- if (element->getDropped()) {
+ if (element.dropped_count()) {
--mDroppedElements[log_id];
}
- if (mOldest[log_id] < element->getRealTime()) {
- mOldest[log_id] = element->getRealTime();
+ if (mOldest[log_id] < element.realtime()) {
+ mOldest[log_id] = element.realtime();
}
if (log_id == LOG_ID_KERNEL) {
return;
}
- uidTable[log_id].subtract(element->getUid(), element);
- if (element->getUid() == AID_SYSTEM) {
- pidSystemTable[log_id].subtract(element->getPid(), 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->getPid(), element);
- tidTable.subtract(element->getTid(), element);
+ pidTable.Subtract(element.pid(), element);
+ tidTable.Subtract(element.tid(), element);
- uint32_t tag = element->getTag();
+ uint32_t tag = element.GetTag();
if (tag) {
if (log_id == LOG_ID_SECURITY) {
- securityTagTable.subtract(tag, element);
+ securityTagTable.Subtract(tag, element);
} else {
- tagTable.subtract(tag, element);
+ tagTable.Subtract(tag, element);
}
}
- if (!element->getDropped()) {
- tagNameTable.subtract(TagNameKey(element), element);
+ 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(LogBufferElement* element) {
+void LogStatistics::Drop(const LogBufferElement& element) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element->getLogId();
- uint16_t size = element->getMsgLen();
+ 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->getRealTime()) {
- mNewestDropped[log_id] = element->getRealTime();
+ if (mNewestDropped[log_id] < element.realtime()) {
+ mNewestDropped[log_id] = element.realtime();
}
- uidTable[log_id].drop(element->getUid(), element);
- if (element->getUid() == AID_SYSTEM) {
- pidSystemTable[log_id].drop(element->getPid(), 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->getPid(), element);
- tidTable.drop(element->getTid(), element);
+ pidTable.Drop(element.pid(), element);
+ tidTable.Drop(element.tid(), element);
- uint32_t tag = element->getTag();
+ uint32_t tag = element.GetTag();
if (tag) {
if (log_id == LOG_ID_SECURITY) {
- securityTagTable.drop(tag, element);
+ securityTagTable.Drop(tag, element);
} else {
- tagTable.drop(tag, element);
+ tagTable.Drop(tag, element);
}
}
- tagNameTable.subtract(TagNameKey(element), element);
+ tagNameTable.Subtract(TagNameKey(element), element);
}
const char* LogStatistics::UidToName(uid_t uid) const {
@@ -283,8 +283,8 @@
++it) {
const PidEntry& entry = it->second;
- if (entry.getUid() == uid) {
- const char* nameTmp = entry.getName();
+ if (entry.uid() == uid) {
+ const char* nameTmp = entry.name();
if (nameTmp) {
if (!name) {
@@ -314,8 +314,8 @@
*worst_sizes = max_entries[0]->getSizes();
// b/24782000: Allow time horizon to extend roughly tenfold, assume average entry length is
// 100 characters.
- if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->getDropped())) {
- *worst = max_entries[0]->getKey();
+ if (*worst_sizes > threshold && *worst_sizes > (10 * max_entries[0]->dropped_count())) {
+ *worst = max_entries[0]->key();
*second_worst_sizes = max_entries[1]->getSizes();
if (*second_worst_sizes < threshold) {
*second_worst_sizes = threshold;
@@ -344,7 +344,7 @@
return;
}
- *worst = max_entries[0]->getKey();
+ *worst = max_entries[0]->key();
*second_worst_sizes = worst_uid_sizes - max_entries[0]->getSizes() + max_entries[1]->getSizes();
}
@@ -393,9 +393,8 @@
if (!nameTmp) nameTmp = allocNameTmp = UidToNameLocked(uid);
if (nameTmp) {
size_t lenSpace = std::max(nameLen - name.length(), (size_t)1);
- size_t len = EntryBaseConstants::total_len -
- EntryBaseConstants::pruned_len - size.length() -
- name.length() - lenSpace - 2;
+ size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
+ lenSpace - 2;
size_t lenNameTmp = strlen(nameTmp);
while ((len < lenNameTmp) && (lenSpace > 1)) {
++len;
@@ -412,11 +411,10 @@
}
std::string UidEntry::format(const LogStatistics& stat, log_id_t id) const REQUIRES(stat.lock_) {
- uid_t uid = getUid();
- std::string name = android::base::StringPrintf("%u", uid);
+ std::string name = android::base::StringPrintf("%u", uid_);
std::string size = android::base::StringPrintf("%zu", getSizes());
- stat.FormatTmp(nullptr, uid, name, size, 6);
+ stat.FormatTmp(nullptr, uid_, name, size, 6);
std::string pruned = "";
if (worstUidEnabledForLogid(id)) {
@@ -424,7 +422,7 @@
for (LogStatistics::uidTable_t::const_iterator it =
stat.uidTable[id].begin();
it != stat.uidTable[id].end(); ++it) {
- totalDropped += it->second.getDropped();
+ totalDropped += it->second.dropped_count();
}
size_t sizes = stat.mSizes[id];
size_t totalSize = stat.mSizesTotal[id];
@@ -434,7 +432,7 @@
size_t entrySize = getSizes();
float virtualEntrySize = entrySize;
int realPermille = virtualEntrySize * 1000.0 / sizes;
- size_t dropped = getDropped();
+ size_t dropped = dropped_count();
if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped);
virtualEntrySize += (float)dropped * totalSize / totalElements;
@@ -461,8 +459,7 @@
change = android::base::StringPrintf(
"%s%d%s", prefix, (permille + 5) / 10, units);
}
- ssize_t spaces = EntryBaseConstants::pruned_len - 2 -
- pruned.length() - change.length();
+ ssize_t spaces = EntryBase::PRUNED_LEN - 2 - pruned.length() - change.length();
if ((spaces <= 0) && pruned.length()) {
spaces = 1;
}
@@ -475,13 +472,13 @@
std::string output = formatLine(name, size, pruned);
- if (uid != AID_SYSTEM) {
+ if (uid_ != AID_SYSTEM) {
return output;
}
static const size_t maximum_sorted_entries = 32;
std::array<const PidEntry*, maximum_sorted_entries> sorted;
- stat.pidSystemTable[id].MaxEntries(uid, 0, &sorted);
+ stat.pidSystemTable[id].MaxEntries(uid_, 0, &sorted);
std::string byPid;
size_t index;
@@ -494,7 +491,7 @@
if (entry->getSizes() <= (getSizes() / 100)) {
break;
}
- if (entry->getDropped()) {
+ if (entry->dropped_count()) {
hasDropped = true;
}
byPid += entry->format(stat, id);
@@ -518,15 +515,13 @@
std::string PidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
REQUIRES(stat.lock_) {
- uid_t uid = getUid();
- pid_t pid = getPid();
- std::string name = android::base::StringPrintf("%5u/%u", pid, uid);
+ std::string name = android::base::StringPrintf("%5u/%u", pid_, uid_);
std::string size = android::base::StringPrintf("%zu", getSizes());
- stat.FormatTmp(getName(), uid, name, size, 12);
+ stat.FormatTmp(name_, uid_, name, size, 12);
std::string pruned = "";
- size_t dropped = getDropped();
+ size_t dropped = dropped_count();
if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped);
}
@@ -543,14 +538,13 @@
std::string TidEntry::format(const LogStatistics& stat, log_id_t /* id */) const
REQUIRES(stat.lock_) {
- uid_t uid = getUid();
- std::string name = android::base::StringPrintf("%5u/%u", getTid(), uid);
+ std::string name = android::base::StringPrintf("%5u/%u", tid(), uid_);
std::string size = android::base::StringPrintf("%zu", getSizes());
- stat.FormatTmp(getName(), uid, name, size, 12);
+ stat.FormatTmp(name_, uid_, name, size, 12);
std::string pruned = "";
- size_t dropped = getDropped();
+ size_t dropped = dropped_count();
if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped);
}
@@ -569,13 +563,12 @@
std::string TagEntry::format(const LogStatistics& /* stat */,
log_id_t /* id */) const {
std::string name;
- uid_t uid = getUid();
- if (uid == (uid_t)-1) {
- name = android::base::StringPrintf("%7u", getKey());
+ if (uid_ == (uid_t)-1) {
+ name = android::base::StringPrintf("%7u", key());
} else {
- name = android::base::StringPrintf("%7u/%u", getKey(), uid);
+ name = android::base::StringPrintf("%7u/%u", key(), uid_);
}
- const char* nameTmp = getName();
+ const char* nameTmp = this->name();
if (nameTmp) {
name += android::base::StringPrintf(
"%*s%s", (int)std::max(14 - name.length(), (size_t)1), "", nameTmp);
@@ -584,7 +577,7 @@
std::string size = android::base::StringPrintf("%zu", getSizes());
std::string pruned = "";
- size_t dropped = getDropped();
+ size_t dropped = dropped_count();
if (dropped) {
pruned = android::base::StringPrintf("%zu", dropped);
}
@@ -602,34 +595,30 @@
std::string TagNameEntry::format(const LogStatistics& /* stat */,
log_id_t /* id */) const {
std::string name;
- pid_t tid = getTid();
- pid_t pid = getPid();
std::string pidstr;
- if (pid != (pid_t)-1) {
- pidstr = android::base::StringPrintf("%u", pid);
- if ((tid != (pid_t)-1) && (tid != pid)) pidstr = "/" + pidstr;
+ if (pid_ != (pid_t)-1) {
+ pidstr = android::base::StringPrintf("%u", pid_);
+ if (tid_ != (pid_t)-1 && tid_ != pid_) pidstr = "/" + pidstr;
}
int len = 9 - pidstr.length();
if (len < 0) len = 0;
- if ((tid == (pid_t)-1) || (tid == pid)) {
+ if (tid_ == (pid_t)-1 || tid_ == pid_) {
name = android::base::StringPrintf("%*s", len, "");
} else {
- name = android::base::StringPrintf("%*u", len, tid);
+ name = android::base::StringPrintf("%*u", len, tid_);
}
name += pidstr;
- uid_t uid = getUid();
- if (uid != (uid_t)-1) {
- name += android::base::StringPrintf("/%u", uid);
+ if (uid_ != (uid_t)-1) {
+ name += android::base::StringPrintf("/%u", uid_);
}
std::string size = android::base::StringPrintf("%zu", getSizes());
- const char* nameTmp = getName();
+ const char* nameTmp = this->name();
if (nameTmp) {
size_t lenSpace = std::max(16 - name.length(), (size_t)1);
- size_t len = EntryBaseConstants::total_len -
- EntryBaseConstants::pruned_len - size.length() -
- name.length() - lenSpace - 2;
+ size_t len = EntryBase::TOTAL_LEN - EntryBase::PRUNED_LEN - size.length() - name.length() -
+ lenSpace - 2;
size_t lenNameTmp = strlen(nameTmp);
while ((len < lenNameTmp) && (lenSpace > 1)) {
++len;
@@ -944,7 +933,7 @@
uid_t LogStatistics::PidToUid(pid_t pid) {
auto lock = std::lock_guard{lock_};
- return pidTable.add(pid)->second.getUid();
+ return pidTable.Add(pid)->second.uid();
}
// caller must free character string
@@ -952,7 +941,7 @@
auto lock = std::lock_guard{lock_};
// An inconvenient truth ... getName() can alter the object
pidTable_t& writablePidTable = const_cast<pidTable_t&>(pidTable);
- const char* name = writablePidTable.add(pid)->second.getName();
+ const char* name = writablePidTable.Add(pid)->second.name();
if (!name) {
return nullptr;
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 7d13ff7..6a46adb 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -65,7 +65,7 @@
static const size_t unordered_map_per_entry_overhead = sizeof(void*);
static const size_t unordered_map_bucket_overhead = sizeof(void*);
- public:
+ public:
size_t size() const {
return map.size();
}
@@ -90,10 +90,10 @@
for (const_iterator it = map.begin(); it != map.end(); ++it) {
const TEntry& entry = it->second;
- if ((uid != AID_ROOT) && (uid != entry.getUid())) {
+ if (uid != AID_ROOT && uid != entry.uid()) {
continue;
}
- if (pid && entry.getPid() && (pid != entry.getPid())) {
+ if (pid && entry.pid() && pid != entry.pid()) {
continue;
}
@@ -113,95 +113,67 @@
}
}
- inline iterator add(const TKey& key, const LogBufferElement* element) {
+ iterator Add(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key);
if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(element))).first;
} else {
- it->second.add(element);
+ it->second.Add(element);
}
return it;
}
- inline iterator add(TKey key) {
+ iterator Add(const TKey& key) {
iterator it = map.find(key);
if (it == map.end()) {
it = map.insert(std::make_pair(key, TEntry(key))).first;
} else {
- it->second.add(key);
+ it->second.Add(key);
}
return it;
}
- void subtract(TKey&& key, const LogBufferElement* element) {
- iterator it = map.find(std::move(key));
- if ((it != map.end()) && it->second.subtract(element)) {
- map.erase(it);
- }
- }
-
- void subtract(const TKey& key, const LogBufferElement* element) {
+ void Subtract(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key);
- if ((it != map.end()) && it->second.subtract(element)) {
+ if (it != map.end() && it->second.Subtract(element)) {
map.erase(it);
}
}
- inline void drop(TKey key, const LogBufferElement* element) {
+ void Drop(const TKey& key, const LogBufferElement& element) {
iterator it = map.find(key);
if (it != map.end()) {
- it->second.drop(element);
+ it->second.Drop(element);
}
}
- inline iterator begin() {
- return map.begin();
- }
- inline const_iterator begin() const {
- return map.begin();
- }
- inline iterator end() {
- return map.end();
- }
- inline const_iterator end() const {
- return map.end();
- }
+ iterator begin() { return map.begin(); }
+ const_iterator begin() const { return map.begin(); }
+ iterator end() { return map.end(); }
+ const_iterator end() const { return map.end(); }
};
-namespace EntryBaseConstants {
-static constexpr size_t pruned_len = 14;
-static constexpr size_t total_len = 80;
-}
+class EntryBase {
+ public:
+ EntryBase() : size_(0) {}
+ explicit EntryBase(const LogBufferElement& element) : size_(element.msg_len()) {}
-struct EntryBase {
- size_t size;
+ size_t getSizes() const { return size_; }
- EntryBase() : size(0) {
- }
- explicit EntryBase(const LogBufferElement* element)
- : size(element->getMsgLen()) {
+ void Add(const LogBufferElement& element) { size_ += element.msg_len(); }
+ bool Subtract(const LogBufferElement& element) {
+ size_ -= element.msg_len();
+ return !size_;
}
- size_t getSizes() const {
- return size;
- }
-
- inline void add(const LogBufferElement* element) {
- size += element->getMsgLen();
- }
- inline bool subtract(const LogBufferElement* element) {
- size -= element->getMsgLen();
- return !size;
- }
+ static constexpr size_t PRUNED_LEN = 14;
+ static constexpr size_t TOTAL_LEN = 80;
static std::string formatLine(const std::string& name,
const std::string& size,
const std::string& pruned) {
- ssize_t drop_len =
- std::max(pruned.length() + 1, EntryBaseConstants::pruned_len);
- ssize_t size_len =
- std::max(size.length() + 1, EntryBaseConstants::total_len -
- name.length() - drop_len - 1);
+ ssize_t drop_len = std::max(pruned.length() + 1, PRUNED_LEN);
+ ssize_t size_len = std::max(size.length() + 1, TOTAL_LEN - name.length() - drop_len - 1);
std::string ret = android::base::StringPrintf(
"%s%*s%*s", name.c_str(), (int)size_len, size.c_str(),
@@ -213,258 +185,220 @@
if (len) ret.erase(pos + 1, len);
return ret + "\n";
}
+
+ private:
+ size_t size_;
};
-struct EntryBaseDropped : public EntryBase {
- size_t dropped;
+class EntryBaseDropped : public EntryBase {
+ public:
+ EntryBaseDropped() : dropped_(0) {}
+ explicit EntryBaseDropped(const LogBufferElement& element)
+ : EntryBase(element), dropped_(element.dropped_count()) {}
- EntryBaseDropped() : dropped(0) {
+ size_t dropped_count() const { return dropped_; }
+
+ void Add(const LogBufferElement& element) {
+ dropped_ += element.dropped_count();
+ EntryBase::Add(element);
}
- explicit EntryBaseDropped(const LogBufferElement* element)
- : EntryBase(element), dropped(element->getDropped()) {
+ bool Subtract(const LogBufferElement& element) {
+ dropped_ -= element.dropped_count();
+ return EntryBase::Subtract(element) && !dropped_;
+ }
+ void Drop(const LogBufferElement& element) {
+ dropped_ += 1;
+ EntryBase::Subtract(element);
}
- size_t getDropped() const {
- return dropped;
- }
-
- inline void add(const LogBufferElement* element) {
- dropped += element->getDropped();
- EntryBase::add(element);
- }
- inline bool subtract(const LogBufferElement* element) {
- dropped -= element->getDropped();
- return EntryBase::subtract(element) && !dropped;
- }
- inline void drop(const LogBufferElement* element) {
- dropped += 1;
- EntryBase::subtract(element);
- }
+ private:
+ size_t dropped_;
};
-struct UidEntry : public EntryBaseDropped {
- const uid_t uid;
- pid_t pid;
+class UidEntry : public EntryBaseDropped {
+ public:
+ explicit UidEntry(const LogBufferElement& element)
+ : EntryBaseDropped(element), uid_(element.uid()), pid_(element.pid()) {}
- explicit UidEntry(const LogBufferElement* element)
- : EntryBaseDropped(element),
- uid(element->getUid()),
- pid(element->getPid()) {
- }
+ uid_t key() const { return uid_; }
+ uid_t uid() const { return key(); }
+ pid_t pid() const { return pid_; }
- inline const uid_t& getKey() const {
- return uid;
- }
- inline const uid_t& getUid() const {
- return getKey();
- }
- inline const pid_t& getPid() const {
- return pid;
- }
-
- inline void add(const LogBufferElement* element) {
- if (pid != element->getPid()) {
- pid = -1;
+ void Add(const LogBufferElement& element) {
+ if (pid_ != element.pid()) {
+ pid_ = -1;
}
- EntryBaseDropped::add(element);
+ EntryBaseDropped::Add(element);
}
std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const;
+
+ private:
+ const uid_t uid_;
+ pid_t pid_;
};
namespace android {
uid_t pidToUid(pid_t pid);
}
-struct PidEntry : public EntryBaseDropped {
- const pid_t pid;
- uid_t uid;
- char* name;
-
+class PidEntry : public EntryBaseDropped {
+ public:
explicit PidEntry(pid_t pid)
: EntryBaseDropped(),
- pid(pid),
- uid(android::pidToUid(pid)),
- name(android::pidToName(pid)) {
- }
- explicit PidEntry(const LogBufferElement* element)
+ pid_(pid),
+ uid_(android::pidToUid(pid)),
+ name_(android::pidToName(pid)) {}
+ explicit PidEntry(const LogBufferElement& element)
: EntryBaseDropped(element),
- pid(element->getPid()),
- uid(element->getUid()),
- name(android::pidToName(pid)) {
- }
+ pid_(element.pid()),
+ uid_(element.uid()),
+ name_(android::pidToName(pid_)) {}
PidEntry(const PidEntry& element)
: EntryBaseDropped(element),
- pid(element.pid),
- uid(element.uid),
- name(element.name ? strdup(element.name) : nullptr) {
- }
- ~PidEntry() {
- free(name);
- }
+ pid_(element.pid_),
+ uid_(element.uid_),
+ name_(element.name_ ? strdup(element.name_) : nullptr) {}
+ ~PidEntry() { free(name_); }
- const pid_t& getKey() const {
- return pid;
- }
- const pid_t& getPid() const {
- return getKey();
- }
- const uid_t& getUid() const {
- return uid;
- }
- const char* getName() const {
- return name;
- }
+ pid_t key() const { return pid_; }
+ pid_t pid() const { return key(); }
+ uid_t uid() const { return uid_; }
+ const char* name() const { return name_; }
- inline void add(pid_t newPid) {
- if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
- free(name);
- name = nullptr;
+ void Add(pid_t new_pid) {
+ if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
+ free(name_);
+ name_ = nullptr;
}
- if (!name) {
- name = android::pidToName(newPid);
+ if (!name_) {
+ name_ = android::pidToName(new_pid);
}
}
- inline void add(const LogBufferElement* element) {
- uid_t incomingUid = element->getUid();
- if (getUid() != incomingUid) {
- uid = incomingUid;
- free(name);
- name = android::pidToName(element->getPid());
+ void Add(const LogBufferElement& element) {
+ uid_t incoming_uid = element.uid();
+ if (uid() != incoming_uid) {
+ uid_ = incoming_uid;
+ free(name_);
+ name_ = android::pidToName(element.pid());
} else {
- add(element->getPid());
+ Add(element.pid());
}
- EntryBaseDropped::add(element);
+ EntryBaseDropped::Add(element);
}
std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const;
+
+ private:
+ const pid_t pid_;
+ uid_t uid_;
+ char* name_;
};
-struct TidEntry : public EntryBaseDropped {
- const pid_t tid;
- pid_t pid;
- uid_t uid;
- char* name;
-
+class TidEntry : public EntryBaseDropped {
+ public:
TidEntry(pid_t tid, pid_t pid)
: EntryBaseDropped(),
- tid(tid),
- pid(pid),
- uid(android::pidToUid(tid)),
- name(android::tidToName(tid)) {
- }
- explicit TidEntry(const LogBufferElement* element)
+ tid_(tid),
+ pid_(pid),
+ uid_(android::pidToUid(tid)),
+ name_(android::tidToName(tid)) {}
+ explicit TidEntry(const LogBufferElement& element)
: EntryBaseDropped(element),
- tid(element->getTid()),
- pid(element->getPid()),
- uid(element->getUid()),
- name(android::tidToName(tid)) {
- }
+ tid_(element.tid()),
+ pid_(element.pid()),
+ uid_(element.uid()),
+ name_(android::tidToName(tid_)) {}
TidEntry(const TidEntry& element)
: EntryBaseDropped(element),
- tid(element.tid),
- pid(element.pid),
- uid(element.uid),
- name(element.name ? strdup(element.name) : nullptr) {
- }
- ~TidEntry() {
- free(name);
- }
+ tid_(element.tid_),
+ pid_(element.pid_),
+ uid_(element.uid_),
+ name_(element.name_ ? strdup(element.name_) : nullptr) {}
+ ~TidEntry() { free(name_); }
- const pid_t& getKey() const {
- return tid;
- }
- const pid_t& getTid() const {
- return getKey();
- }
- const pid_t& getPid() const {
- return pid;
- }
- const uid_t& getUid() const {
- return uid;
- }
- const char* getName() const {
- return name;
- }
+ pid_t key() const { return tid_; }
+ pid_t tid() const { return key(); }
+ pid_t pid() const { return pid_; }
+ uid_t uid() const { return uid_; }
+ const char* name() const { return name_; }
- inline void add(pid_t incomingTid) {
- if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
- free(name);
- name = nullptr;
+ void Add(pid_t incomingTid) {
+ if (name_ && !fastcmp<strncmp>(name_, "zygote", 6)) {
+ free(name_);
+ name_ = nullptr;
}
- if (!name) {
- name = android::tidToName(incomingTid);
+ if (!name_) {
+ name_ = android::tidToName(incomingTid);
}
}
- inline void add(const LogBufferElement* element) {
- uid_t incomingUid = element->getUid();
- pid_t incomingPid = element->getPid();
- if ((getUid() != incomingUid) || (getPid() != incomingPid)) {
- uid = incomingUid;
- pid = incomingPid;
- free(name);
- name = android::tidToName(element->getTid());
+ void Add(const LogBufferElement& 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());
} else {
- add(element->getTid());
+ Add(element.tid());
}
- EntryBaseDropped::add(element);
+ EntryBaseDropped::Add(element);
}
std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const;
+
+ private:
+ const pid_t tid_;
+ pid_t pid_;
+ uid_t uid_;
+ char* name_;
};
-struct TagEntry : public EntryBaseDropped {
- const uint32_t tag;
- pid_t pid;
- uid_t uid;
-
- explicit TagEntry(const LogBufferElement* element)
+class TagEntry : public EntryBaseDropped {
+ public:
+ explicit TagEntry(const LogBufferElement& element)
: EntryBaseDropped(element),
- tag(element->getTag()),
- pid(element->getPid()),
- uid(element->getUid()) {
- }
+ tag_(element.GetTag()),
+ pid_(element.pid()),
+ uid_(element.uid()) {}
- const uint32_t& getKey() const {
- return tag;
- }
- const pid_t& getPid() const {
- return pid;
- }
- const uid_t& getUid() const {
- return uid;
- }
- const char* getName() const {
- return android::tagToName(tag);
- }
+ 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_); }
- inline void add(const LogBufferElement* element) {
- if (uid != element->getUid()) {
- uid = -1;
+ void Add(const LogBufferElement& element) {
+ if (uid_ != element.uid()) {
+ uid_ = -1;
}
- if (pid != element->getPid()) {
- pid = -1;
+ if (pid_ != element.pid()) {
+ pid_ = -1;
}
- EntryBaseDropped::add(element);
+ EntryBaseDropped::Add(element);
}
std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const;
+
+ private:
+ const uint32_t tag_;
+ pid_t pid_;
+ uid_t uid_;
};
struct TagNameKey {
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 LogBufferElement& element) : alloc(nullptr), name("", strlen("")) {
+ if (element.IsBinary()) {
+ uint32_t tag = element.GetTag();
if (tag) {
const char* cp = android::tagToName(tag);
if (cp) {
@@ -478,13 +412,13 @@
name = std::string_view(alloc->c_str(), alloc->size());
return;
}
- const char* msg = element->getMsg();
+ const char* msg = element.msg();
if (!msg) {
name = std::string_view("chatty", strlen("chatty"));
return;
}
++msg;
- uint16_t len = element->getMsgLen();
+ uint16_t len = element.msg_len();
len = (len <= 1) ? 0 : strnlen(msg, len - 1);
if (!len) {
name = std::string_view("<NULL>", strlen("<NULL>"));
@@ -544,54 +478,43 @@
}
};
-struct TagNameEntry : public EntryBase {
- pid_t tid;
- pid_t pid;
- uid_t uid;
- TagNameKey name;
-
- explicit TagNameEntry(const LogBufferElement* element)
+class TagNameEntry : public EntryBase {
+ public:
+ explicit TagNameEntry(const LogBufferElement& element)
: EntryBase(element),
- tid(element->getTid()),
- pid(element->getPid()),
- uid(element->getUid()),
- name(element) {
- }
+ tid_(element.tid()),
+ pid_(element.pid()),
+ uid_(element.uid()),
+ name_(element) {}
- const TagNameKey& getKey() const {
- return name;
- }
- const pid_t& getTid() const {
- return tid;
- }
- const pid_t& getPid() const {
- return pid;
- }
- const uid_t& getUid() const {
- return uid;
- }
- const char* getName() const {
- return name.data();
- }
- size_t getNameAllocLength() const {
- return name.getAllocLength();
- }
+ const TagNameKey& key() const { return name_; }
+ pid_t tid() const { return tid_; }
+ pid_t pid() const { return pid_; }
+ uid_t uid() const { return uid_; }
+ const char* name() const { return name_.data(); }
+ size_t getNameAllocLength() const { return name_.getAllocLength(); }
- inline void add(const LogBufferElement* element) {
- if (uid != element->getUid()) {
- uid = -1;
+ void Add(const LogBufferElement& element) {
+ if (uid_ != element.uid()) {
+ uid_ = -1;
}
- if (pid != element->getPid()) {
- pid = -1;
+ if (pid_ != element.pid()) {
+ pid_ = -1;
}
- if (tid != element->getTid()) {
- tid = -1;
+ if (tid_ != element.tid()) {
+ tid_ = -1;
}
- EntryBase::add(element);
+ EntryBase::Add(element);
}
std::string formatHeader(const std::string& name, log_id_t id) const;
std::string format(const LogStatistics& stat, log_id_t id) const;
+
+ private:
+ pid_t tid_;
+ pid_t pid_;
+ uid_t uid_;
+ TagNameKey name_;
};
// Log Statistics
@@ -645,11 +568,11 @@
(pidTable.size() * sizeof(pidTable_t::iterator)) +
(tagTable.size() * sizeof(tagTable_t::iterator));
for (auto it : pidTable) {
- const char* name = it.second.getName();
+ const char* name = it.second.name();
if (name) size += strlen(name) + 1;
}
for (auto it : tidTable) {
- const char* name = it.second.getName();
+ const char* name = it.second.name();
if (name) size += strlen(name) + 1;
}
for (auto it : tagNameTable) size += it.second.getNameAllocLength();
@@ -667,14 +590,14 @@
LogStatistics(bool enable_statistics);
void AddTotal(log_id_t log_id, uint16_t size) EXCLUDES(lock_);
- void Add(LogBufferElement* entry) EXCLUDES(lock_);
- void Subtract(LogBufferElement* entry) EXCLUDES(lock_);
+ void Add(const LogBufferElement& entry) EXCLUDES(lock_);
+ void Subtract(const LogBufferElement& entry) EXCLUDES(lock_);
// entry->setDropped(1) must follow this call
- void Drop(LogBufferElement* entry) EXCLUDES(lock_);
+ void Drop(const LogBufferElement& entry) EXCLUDES(lock_);
// Correct for coalescing two entries referencing dropped content
- void Erase(LogBufferElement* element) EXCLUDES(lock_) {
+ void Erase(const LogBufferElement& element) EXCLUDES(lock_) {
auto lock = std::lock_guard{lock_};
- log_id_t log_id = element->getLogId();
+ log_id_t log_id = element.log_id();
--mElements[log_id];
--mDroppedElements[log_id];
}
diff --git a/logd/LogWhiteBlackList.h b/logd/LogWhiteBlackList.h
index 0e4e837..447ab87 100644
--- a/logd/LogWhiteBlackList.h
+++ b/logd/LogWhiteBlackList.h
@@ -43,9 +43,7 @@
return mPid;
}
- int cmp(LogBufferElement* e) const {
- return cmp(e->getUid(), e->getPid());
- }
+ int cmp(LogBufferElement* e) const { return cmp(e->uid(), e->pid()); }
std::string format();
};
diff --git a/logd/LogWriter.h b/logd/LogWriter.h
index b6c5b67..d43c604 100644
--- a/logd/LogWriter.h
+++ b/logd/LogWriter.h
@@ -23,8 +23,7 @@
// An interface for writing logs to a reader.
class LogWriter {
public:
- LogWriter(uid_t uid, bool privileged, bool can_read_security_logs)
- : uid_(uid), privileged_(privileged), can_read_security_logs_(can_read_security_logs) {}
+ LogWriter(uid_t uid, bool privileged) : uid_(uid), privileged_(privileged) {}
virtual ~LogWriter() {}
virtual bool Write(const logger_entry& entry, const char* msg) = 0;
@@ -35,12 +34,10 @@
uid_t uid() const { return uid_; }
bool privileged() const { return privileged_; }
- bool can_read_security_logs() const { return can_read_security_logs_; }
private:
uid_t uid_;
// If this writer sees logs from all UIDs or only its own UID. See clientHasLogCredentials().
bool privileged_;
- bool can_read_security_logs_; // If this writer sees security logs. See CanReadSecurityLogs().
};
\ No newline at end of file
diff --git a/logd/SimpleLogBuffer.cpp b/logd/SimpleLogBuffer.cpp
index 1c83428..79ce069 100644
--- a/logd/SimpleLogBuffer.cpp
+++ b/logd/SimpleLogBuffer.cpp
@@ -44,7 +44,7 @@
if (oldest_[log_id]) {
it = *oldest_[log_id];
}
- while (it != logs().end() && it->getLogId() != log_id) {
+ while (it != logs().end() && it->log_id() != log_id) {
it++;
}
if (it != logs().end()) {
@@ -102,21 +102,42 @@
}
void SimpleLogBuffer::LogInternal(LogBufferElement&& elem) {
- log_id_t log_id = elem.getLogId();
+ log_id_t log_id = elem.log_id();
logs_.emplace_back(std::move(elem));
- stats_->Add(&logs_.back());
+ stats_->Add(logs_.back());
MaybePrune(log_id);
reader_list_->NotifyNewLog(1 << log_id);
}
-uint64_t SimpleLogBuffer::FlushTo(
- LogWriter* writer, uint64_t start, pid_t* last_tid,
- const std::function<FlushToResult(const LogBufferElement* element)>& filter) {
+// These extra parameters are only required for chatty, but since they're a no-op for
+// SimpleLogBuffer, it's easier to include them here, then to duplicate FlushTo() for
+// ChattyLogBuffer.
+class ChattyFlushToState : public FlushToState {
+ public:
+ ChattyFlushToState(uint64_t start, LogMask log_mask) : FlushToState(start, log_mask) {}
+
+ pid_t* last_tid() { return last_tid_; }
+
+ private:
+ pid_t last_tid_[LOG_ID_MAX] = {};
+};
+
+std::unique_ptr<FlushToState> SimpleLogBuffer::CreateFlushToState(uint64_t start,
+ LogMask log_mask) {
+ return std::make_unique<ChattyFlushToState>(start, log_mask);
+}
+
+bool SimpleLogBuffer::FlushTo(
+ LogWriter* writer, FlushToState& abstract_state,
+ const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
+ log_time realtime, uint16_t dropped_count)>& filter) {
auto shared_lock = SharedLock{lock_};
+ auto& state = reinterpret_cast<ChattyFlushToState&>(abstract_state);
+
std::list<LogBufferElement>::iterator it;
- if (start <= 1) {
+ if (state.start() <= 1) {
// client wants to start from the beginning
it = logs_.begin();
} else {
@@ -125,61 +146,57 @@
for (it = logs_.end(); it != logs_.begin();
/* do nothing */) {
--it;
- if (it->getSequence() <= start) {
+ if (it->sequence() == state.start()) {
+ break;
+ } else if (it->sequence() < state.start()) {
it++;
break;
}
}
}
- uint64_t curr = start;
-
for (; it != logs_.end(); ++it) {
LogBufferElement& element = *it;
- if (!writer->privileged() && element.getUid() != writer->uid()) {
+ state.set_start(element.sequence());
+
+ if (!writer->privileged() && element.uid() != writer->uid()) {
continue;
}
- if (!writer->can_read_security_logs() && element.getLogId() == LOG_ID_SECURITY) {
+ if (((1 << element.log_id()) & state.log_mask()) == 0) {
continue;
}
if (filter) {
- FlushToResult ret = filter(&element);
- if (ret == FlushToResult::kSkip) {
+ FilterResult ret = filter(element.log_id(), element.pid(), element.sequence(),
+ element.realtime(), element.dropped_count());
+ if (ret == FilterResult::kSkip) {
continue;
}
- if (ret == FlushToResult::kStop) {
+ if (ret == FilterResult::kStop) {
break;
}
}
- bool same_tid = false;
- if (last_tid) {
- same_tid = last_tid[element.getLogId()] == element.getTid();
- // Dropped (chatty) immediately following a valid log from the
- // same source in the same log buffer indicates we have a
- // multiple identical squash. chatty that differs source
- // is due to spam filter. chatty to chatty of different
- // source is also due to spam filter.
- last_tid[element.getLogId()] =
- (element.getDropped() && !same_tid) ? 0 : element.getTid();
- }
+ bool same_tid = state.last_tid()[element.log_id()] == element.tid();
+ // Dropped (chatty) immediately following a valid log from the same source in the same log
+ // buffer indicates we have a multiple identical squash. chatty that differs source is due
+ // to spam filter. chatty to chatty of different source is also due to spam filter.
+ state.last_tid()[element.log_id()] =
+ (element.dropped_count() && !same_tid) ? 0 : element.tid();
shared_lock.unlock();
-
// We never prune logs equal to or newer than any LogReaderThreads' `start` value, so the
// `element` pointer is safe here without the lock
- curr = element.getSequence();
if (!element.FlushTo(writer, stats_, same_tid)) {
- return FLUSH_ERROR;
+ return false;
}
-
shared_lock.lock_shared();
}
- return curr;
+ state.set_start(state.start() + 1);
+ return true;
}
// clear all rows of type "id" from the buffer.
@@ -271,22 +288,22 @@
while (it != logs_.end()) {
LogBufferElement& element = *it;
- if (element.getLogId() != id) {
+ if (element.log_id() != id) {
++it;
continue;
}
- if (caller_uid != 0 && element.getUid() != caller_uid) {
+ if (caller_uid != 0 && element.uid() != caller_uid) {
++it;
continue;
}
- if (oldest && oldest->start() <= element.getSequence()) {
+ if (oldest && oldest->start() <= element.sequence()) {
KickReader(oldest, id, prune_rows);
return true;
}
- stats_->Subtract(&element);
+ stats_->Subtract(element);
it = Erase(it);
if (--prune_rows == 0) {
return false;
diff --git a/logd/SimpleLogBuffer.h b/logd/SimpleLogBuffer.h
index 9a2d01a..a2ab881 100644
--- a/logd/SimpleLogBuffer.h
+++ b/logd/SimpleLogBuffer.h
@@ -35,9 +35,11 @@
int Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid, const char* msg,
uint16_t len) override;
- uint64_t FlushTo(
- LogWriter* writer, uint64_t start, pid_t* lastTid,
- const std::function<FlushToResult(const LogBufferElement* element)>& filter) override;
+ std::unique_ptr<FlushToState> CreateFlushToState(uint64_t start, LogMask log_mask) override;
+ bool FlushTo(LogWriter* writer, FlushToState& state,
+ const std::function<FilterResult(log_id_t log_id, pid_t pid, uint64_t sequence,
+ log_time realtime, uint16_t dropped_count)>&
+ filter) override;
bool Clear(log_id_t id, uid_t uid) override;
unsigned long GetSize(log_id_t id) override;