Merge "Revert "logcat: remove the -S option."" into main
diff --git a/liblog/logprint.cpp b/liblog/logprint.cpp
index e949c65..aece1fa 100644
--- a/liblog/logprint.cpp
+++ b/liblog/logprint.cpp
@@ -1088,59 +1088,64 @@
}
/*
- * Convert to printable from message to p buffer, return string length. If p is
- * NULL, do not copy, but still return the expected string length.
+ * Convert to printable from src to dst buffer, returning dst bytes used.
+ * If dst is NULL, do not copy, but still return the dst bytes required.
*/
-size_t convertPrintable(char* p, const char* message, size_t messageLen) {
- char* begin = p;
- bool print = p != NULL;
- mbstate_t mb_state = {};
+size_t convertPrintable(char* dst0, const char* src0, size_t n) {
+ char* dst = dst0;
+ const unsigned char* src = reinterpret_cast<const unsigned char*>(src0);
+ mbstate_t mbs = {};
- while (messageLen) {
- char buf[6];
- ssize_t len = sizeof(buf) - 1;
- if ((size_t)len > messageLen) {
- len = messageLen;
+ bool print = (dst != nullptr);
+
+ while (n > 0) {
+ // ASCII fast path to cover most logging; space and tab aren't escaped,
+ // but backslash is.
+ if ((*src >= ' ' && *src < 0x7f && *src != '\\') || *src == '\t') {
+ if (print) *dst = *src;
+ dst++;
+ src++;
+ n--;
+ continue;
}
- len = mbrtowc(nullptr, message, len, &mb_state);
- if (len <= 0) {
- snprintf(buf, sizeof(buf), "\\x%02X", static_cast<unsigned char>(*message));
- len = 1;
+ // Unprintable fast path #1: single-character C escapes.
+ if ((*src >= '\a' && *src <= '\r') || *src == '\\') {
+ if (print) {
+ dst[0] = '\\';
+ dst[1] = (*src == '\\') ? '\\' : "abtnvfr"[*src - '\a'];
+ }
+ dst += 2;
+ src++;
+ n--;
+ continue;
+ }
+ // Unprintable fast path #2: everything else below space, plus DEL.
+ if (*src < ' ' || *src == 0x7f) {
+ if (print) sprintf(dst, "\\x%02X", *src);
+ dst += 4;
+ src++;
+ n--;
+ continue;
+ }
+
+ // Are we at the start of a valid UTF-8 encoding?
+ ssize_t len = mbrtowc(nullptr, reinterpret_cast<const char*>(src), n, &mbs);
+ if (len > 0) {
+ if (print) memcpy(dst, src, len);
+ dst += len;
+ src += len;
+ n -= len;
} else {
- buf[0] = '\0';
- if (len == 1) {
- if (*message == '\a') {
- strcpy(buf, "\\a");
- } else if (*message == '\b') {
- strcpy(buf, "\\b");
- } else if (*message == '\t') {
- strcpy(buf, "\t"); /* Do not escape tabs */
- } else if (*message == '\v') {
- strcpy(buf, "\\v");
- } else if (*message == '\f') {
- strcpy(buf, "\\f");
- } else if (*message == '\r') {
- strcpy(buf, "\\r");
- } else if (*message == '\\') {
- strcpy(buf, "\\\\");
- } else if ((*message < ' ') || (*message >= 0x7f)) {
- snprintf(buf, sizeof(buf), "\\x%02X", static_cast<unsigned char>(*message));
- }
- }
- if (!buf[0]) {
- strncpy(buf, message, len);
- buf[len] = '\0';
- }
+ // Assume it's just one bad byte, and try again after escaping it.
+ if (print) sprintf(dst, "\\x%02X", *src);
+ dst += 4;
+ src++;
+ n--;
}
- if (print) {
- strcpy(p, buf);
- }
- p += strlen(buf);
- message += len;
- messageLen -= len;
}
- return p - begin;
+ if (print) *dst = '\0';
+ return dst - dst0;
}
#ifdef __ANDROID__
diff --git a/liblog/properties.cpp b/liblog/properties.cpp
index 7ab5cc8..657901a 100644
--- a/liblog/properties.cpp
+++ b/liblog/properties.cpp
@@ -315,4 +315,8 @@
return 1;
}
+int __android_log_security() {
+ return 0;
+}
+
#endif
diff --git a/liblog/tests/Android.bp b/liblog/tests/Android.bp
index 06b6126..f5c2680 100644
--- a/liblog/tests/Android.bp
+++ b/liblog/tests/Android.bp
@@ -33,15 +33,16 @@
"-Wall",
"-Wextra",
"-Werror",
+ "-Wno-unused-result",
"-fno-builtin",
],
shared_libs: [
- "libm",
"libbase",
"libcutils",
],
static_libs: ["liblog"],
srcs: ["liblog_benchmark.cpp"],
+ host_supported: true,
}
// -----------------------------------------------------------------------------
@@ -54,6 +55,7 @@
"liblog_convertPrintable_fuzzer.cpp",
],
static_libs: ["liblog"],
+ host_supported: true,
}
// -----------------------------------------------------------------------------
diff --git a/liblog/tests/liblog_benchmark.cpp b/liblog/tests/liblog_benchmark.cpp
index 5ca2c8c..6dc5da6 100644
--- a/liblog/tests/liblog_benchmark.cpp
+++ b/liblog/tests/liblog_benchmark.cpp
@@ -18,6 +18,7 @@
#include <inttypes.h>
#include <poll.h>
#include <sched.h>
+#include <signal.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
@@ -34,6 +35,10 @@
#include <log/log_read.h>
#include <private/android_logger.h>
+#include "test_utils.h"
+
+size_t convertPrintable(char*, const char*, size_t);
+
BENCHMARK_MAIN();
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
@@ -194,7 +199,7 @@
pmsg_header.pid = getpid();
android_log_header_t header;
- header.tid = gettid();
+ header.tid = 0;
header.realtime.tv_sec = ts.tv_sec;
header.realtime.tv_nsec = ts.tv_nsec;
@@ -280,7 +285,7 @@
buffer->pmsg_header.uid = getuid();
buffer->pmsg_header.pid = getpid();
- buffer->header.tid = gettid();
+ buffer->header.tid = 0;
buffer->header.realtime.tv_sec = ts.tv_sec;
buffer->header.realtime.tv_nsec = ts.tv_nsec;
@@ -354,7 +359,7 @@
buffer->pmsg_header.uid = getuid();
buffer->pmsg_header.pid = getpid();
- buffer->header.tid = gettid();
+ buffer->header.tid = 0;
buffer->header.realtime.tv_sec = ts.tv_sec;
buffer->header.realtime.tv_nsec = ts.tv_nsec;
@@ -428,7 +433,7 @@
buffer->pmsg_header.uid = getuid();
buffer->pmsg_header.pid = getpid();
- buffer->header.tid = gettid();
+ buffer->header.tid = 0;
buffer->header.realtime.tv_sec = ts.tv_sec;
buffer->header.realtime.tv_nsec = ts.tv_nsec;
@@ -500,7 +505,7 @@
buffer->pmsg_header.uid = getuid();
buffer->pmsg_header.pid = getpid();
- buffer->header.tid = gettid();
+ buffer->header.tid = 0;
buffer->header.realtime.tv_sec = ts.tv_sec;
buffer->header.realtime.tv_nsec = ts.tv_nsec;
@@ -633,7 +638,7 @@
return l;
}
-static const int alarm_time = 3;
+static const int alarm_time = getAlarmSeconds(3);
/*
* Measure the time it takes for the logd posting call to acquire the
@@ -787,9 +792,6 @@
}
BENCHMARK(BM_is_loggable);
-/*
- * Measure the time it takes for __android_log_security.
- */
static void BM_security(benchmark::State& state) {
while (state.KeepRunning()) {
__android_log_security();
@@ -997,3 +999,33 @@
android::base::SetProperty("log.tag." + test_log_tag, "");
}
BENCHMARK(BM_log_verbose_overhead);
+
+static void BM_log_convertPrintable_ascii(benchmark::State& state) {
+ char buf[BUFSIZ];
+ const char* s = "hello, world! this is a plain ASCII string 1234.";
+ size_t n = strlen(s);
+ for (auto _ : state) {
+ convertPrintable(buf, s, n);
+ }
+}
+BENCHMARK(BM_log_convertPrintable_ascii);
+
+static void BM_log_convertPrintable_non_printable(benchmark::State& state) {
+ char buf[BUFSIZ];
+ const char* s = "hello,\x01world!\x02this is a plain ASCII string 1234\x7f";
+ size_t n = strlen(s);
+ for (auto _ : state) {
+ convertPrintable(buf, s, n);
+ }
+}
+BENCHMARK(BM_log_convertPrintable_non_printable);
+
+static void BM_log_convertPrintable_non_ascii(benchmark::State& state) {
+ char buf[BUFSIZ];
+ const char* s = "동해 물과 백두산이 마르고 닳도록, 하느님이 보우하사 우리나라 만세.";
+ size_t n = strlen(s);
+ for (auto _ : state) {
+ convertPrintable(buf, s, n);
+ }
+}
+BENCHMARK(BM_log_convertPrintable_non_ascii);
diff --git a/liblog/tests/liblog_convertPrintable_fuzzer.cpp b/liblog/tests/liblog_convertPrintable_fuzzer.cpp
index f4e376a..a362381 100644
--- a/liblog/tests/liblog_convertPrintable_fuzzer.cpp
+++ b/liblog/tests/liblog_convertPrintable_fuzzer.cpp
@@ -16,7 +16,7 @@
#include <fuzzer/FuzzedDataProvider.h>
-size_t convertPrintable(char* p, const char* message, size_t messageLen);
+size_t convertPrintable(char*, const char*, size_t);
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t length) {
FuzzedDataProvider dataProvider(data, length);
diff --git a/liblog/tests/liblog_test.cpp b/liblog/tests/liblog_test.cpp
index 501f25d..cde5a5b 100644
--- a/liblog/tests/liblog_test.cpp
+++ b/liblog/tests/liblog_test.cpp
@@ -46,6 +46,8 @@
#include <private/android_filesystem_config.h>
#include <private/android_logger.h>
+#include "test_utils.h"
+
using android::base::make_scope_guard;
// #define ENABLE_FLAKY_TESTS
@@ -70,12 +72,6 @@
void operator()(struct logger_list* list) { android_logger_list_close(list); }
};
-// Devices can set a system property indicating a slower device, giving a
-// multiplier to use for timeouts. If the device has set this property, we use it.
-static unsigned int getAlarmSeconds(unsigned int seconds) {
- return seconds * android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
-}
-
// This function is meant to be used for most log tests, it does the following:
// 1) Open the log_buffer with a blocking reader
// 2) Write the messages via write_messages
diff --git a/liblog/tests/log_wrap_test.cpp b/liblog/tests/log_wrap_test.cpp
index 891ceb7..1373c2a 100644
--- a/liblog/tests/log_wrap_test.cpp
+++ b/liblog/tests/log_wrap_test.cpp
@@ -28,6 +28,8 @@
#include <log/log_read.h>
#include <log/log_time.h>
+#include "test_utils.h"
+
#ifdef __ANDROID__
static void read_with_wrap() {
// Read the last line in the log to get a starting timestamp. We're assuming
@@ -68,7 +70,7 @@
struct sigaction ignore = {.sa_handler = [](int) { _exit(0); }};
struct sigaction old_sigaction;
sigaction(SIGALRM, &ignore, &old_sigaction);
- alarm(10);
+ alarm(getAlarmSeconds(5));
android::base::Timer timer;
read_with_wrap();
diff --git a/liblog/tests/logprint_test.cpp b/liblog/tests/logprint_test.cpp
index 8475699..dac8c48 100644
--- a/liblog/tests/logprint_test.cpp
+++ b/liblog/tests/logprint_test.cpp
@@ -24,7 +24,7 @@
using namespace std::string_literals;
-size_t convertPrintable(char* p, const char* message, size_t messageLen);
+size_t convertPrintable(char*, const char*, size_t);
TEST(liblog, convertPrintable_ascii) {
auto input = "easy string, output same";
@@ -32,6 +32,7 @@
EXPECT_EQ(output_size, strlen(input));
char output[output_size + 1];
+ memset(output, 'x', sizeof(output));
output_size = convertPrintable(output, input, strlen(input));
EXPECT_EQ(output_size, strlen(input));
@@ -39,18 +40,19 @@
}
TEST(liblog, convertPrintable_escapes) {
- std::string input = "escape\x00\x7f\a\b\t\v\f\r\\"s;
+ std::string input = "escape\x00\x7f\a\b\t\n\v\f\r\\"s;
// We want to test escaping of ASCII NUL at the end too.
auto input_size = input.size() + 1;
// Note that \t is not escaped.
- std::string expected_output = "escape\\x00\\x7F\\a\\b\t\\v\\f\\r\\\\\\x00"s;
+ std::string expected_output = "escape\\x00\\x7F\\a\\b\t\\n\\v\\f\\r\\\\\\x00"s;
auto expected_output_size = expected_output.size();
auto output_size = convertPrintable(nullptr, input.c_str(), input_size);
EXPECT_EQ(output_size, expected_output_size) << input_size;
char output[output_size + 1];
+ memset(output, 'x', sizeof(output));
output_size = convertPrintable(output, input.c_str(), input_size);
EXPECT_EQ(output_size, expected_output_size);
@@ -65,6 +67,7 @@
EXPECT_EQ(output_size, strlen(input));
char output[output_size + 1];
+ memset(output, 'x', sizeof(output));
output_size = convertPrintable(output, input, strlen(input));
EXPECT_EQ(output_size, strlen(input));
@@ -79,6 +82,7 @@
EXPECT_EQ(output_size, strlen(expected_output));
char output[output_size + 1];
+ memset(output, 'x', sizeof(output));
output_size = convertPrintable(output, input, strlen(input));
EXPECT_EQ(output_size, strlen(expected_output));
@@ -97,6 +101,7 @@
EXPECT_EQ(output_size, strlen(expected_output));
char output[output_size + 1];
+ memset(output, 'x', sizeof(output));
output_size = convertPrintable(output, input, strlen(input));
EXPECT_EQ(output_size, strlen(expected_output));
diff --git a/liblog/tests/test_utils.h b/liblog/tests/test_utils.h
new file mode 100644
index 0000000..ee1668a
--- /dev/null
+++ b/liblog/tests/test_utils.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2023 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 <android-base/properties.h>
+
+// Devices can set a system property indicating a slower device, giving a
+// multiplier to use for timeouts. If the device has set this property, we use it.
+static unsigned int getAlarmSeconds(unsigned int seconds) {
+ return seconds * android::base::GetIntProperty("ro.hw_timeout_multiplier", 1);
+}
diff --git a/logd/LogKlog.cpp b/logd/LogKlog.cpp
index 0793f10..8f27694 100644
--- a/logd/LogKlog.cpp
+++ b/logd/LogKlog.cpp
@@ -41,8 +41,6 @@
static const char suspendStr[] = "PM: suspend entry ";
static const char resumeStr[] = "PM: suspend exit ";
static const char suspendedStr[] = "suspended for ";
-static const char healthdStr[] = "healthd";
-static const char batteryStr[] = ": battery ";
static const char auditStr[] = " audit(";
static const char klogdStr[] = "logd.klogd: ";
@@ -313,15 +311,6 @@
(((b += strlen(resumeStr)) - cp) < len)) {
len -= b - cp;
calculateCorrection(now, b, len);
- } else if (((b = android::strnstr(cp, len, healthdStr))) &&
- (((b += strlen(healthdStr)) - cp) < len) &&
- ((b = android::strnstr(b, len -= b - cp, batteryStr))) &&
- (((b += strlen(batteryStr)) - cp) < len)) {
- // NB: healthd is roughly 150us late, so we use it instead to
- // trigger a check for ntp-induced or hardware clock drift.
- log_time real(CLOCK_REALTIME);
- log_time mono(CLOCK_MONOTONIC);
- correction = (real < mono) ? log_time(log_time::EPOCH) : (real - mono);
} else if (((b = android::strnstr(cp, len, suspendedStr))) &&
(((b += strlen(suspendedStr)) - cp) < len)) {
len -= b - cp;
@@ -345,6 +334,17 @@
correction += real;
}
}
+ } else {
+ static time_t last_correction_time_utc = 0;
+ time_t current_time_utc = time(nullptr);
+ if (current_time_utc < last_correction_time_utc ||
+ current_time_utc - last_correction_time_utc > 60) {
+ log_time real(CLOCK_REALTIME);
+ log_time mono(CLOCK_MONOTONIC);
+ correction = (real < mono) ? log_time(log_time::EPOCH) : (real - mono);
+
+ last_correction_time_utc = current_time_utc;
+ }
}
convertMonotonicToReal(now);
diff --git a/logd/libaudit.cpp b/logd/libaudit.cpp
index ccea0a2..a305fb7 100644
--- a/logd/libaudit.cpp
+++ b/logd/libaudit.cpp
@@ -43,9 +43,7 @@
if (rep.nlh.nlmsg_type == NLMSG_ERROR) {
audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, 0);
rc = reinterpret_cast<struct nlmsgerr*>(rep.data)->error;
- if (rc) {
- return -rc;
- }
+ return rc;
}
return 0;