Merge "Remove libcorkscrew."
diff --git a/liblog/tests/Android.mk b/liblog/tests/Android.mk
index db06cf7..d1d9115 100644
--- a/liblog/tests/Android.mk
+++ b/liblog/tests/Android.mk
@@ -32,7 +32,7 @@
benchmark_src_files := \
benchmark_main.cpp \
- liblog_benchmark.cpp \
+ liblog_benchmark.cpp
# Build benchmarks for the device. Run with:
# adb shell liblog-benchmarks
@@ -59,10 +59,22 @@
-g \
-Wall -Wextra \
-Werror \
- -fno-builtin \
+ -fno-builtin
test_src_files := \
- liblog_test.cpp \
+ liblog_test.cpp
+
+# to prevent breaking the build if bionic not relatively visible to us
+ifneq ($(wildcard $(LOCAL_PATH)/../../../../bionic/libc/bionic/libc_logging.cpp),)
+
+test_src_files += \
+ libc_test.cpp
+
+ifndef ($(TARGET_USES_LOGD),false)
+test_c_flags += -DTARGET_USES_LOGD
+endif
+
+endif
# Build tests for the device (with .so). Run with:
# adb shell /data/nativetest/liblog-unit-tests/liblog-unit-tests
diff --git a/liblog/tests/libc_test.cpp b/liblog/tests/libc_test.cpp
new file mode 100644
index 0000000..0abc375
--- /dev/null
+++ b/liblog/tests/libc_test.cpp
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2014 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 <fcntl.h>
+#include <sys/cdefs.h>
+
+#include <gtest/gtest.h>
+
+// Should be in bionic test suite, *but* we are using liblog to confirm
+// end-to-end logging, so let the overly cute oedipus complex begin ...
+#include "../../../../bionic/libc/bionic/libc_logging.cpp" // not Standalone
+#define _ANDROID_LOG_H // Priorities redefined
+#define _LIBS_LOG_LOG_H // log ids redefined
+typedef unsigned char log_id_t; // log_id_t missing as a result
+#ifdef TARGET_USES_LOGD
+#define _LIBS_LOG_LOG_READ_H // log_time redefined
+#endif
+
+#include <log/log.h>
+#include <log/logger.h>
+#include <log/log_read.h>
+
+TEST(libc, __libc_android_log_event_int) {
+ struct logger_list *logger_list;
+
+ pid_t pid = getpid();
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ LOG_ID_EVENTS, O_RDONLY | O_NDELAY, 1000, pid)));
+
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ int value = ts.tv_nsec;
+
+ __libc_android_log_event_int(0, value);
+ usleep(1000000);
+
+ int count = 0;
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ ASSERT_EQ(log_msg.entry.pid, pid);
+
+ if ((log_msg.entry.len != (4 + 1 + 4))
+ || ((int)log_msg.id() != LOG_ID_EVENTS)) {
+ continue;
+ }
+
+ char *eventData = log_msg.msg();
+
+ int incoming = (eventData[0] & 0xFF) |
+ ((eventData[1] & 0xFF) << 8) |
+ ((eventData[2] & 0xFF) << 16) |
+ ((eventData[3] & 0xFF) << 24);
+
+ if (incoming != 0) {
+ continue;
+ }
+
+ if (eventData[4] != EVENT_TYPE_INT) {
+ continue;
+ }
+
+ incoming = (eventData[4 + 1 + 0] & 0xFF) |
+ ((eventData[4 + 1 + 1] & 0xFF) << 8) |
+ ((eventData[4 + 1 + 2] & 0xFF) << 16) |
+ ((eventData[4 + 1 + 3] & 0xFF) << 24);
+
+ if (incoming == value) {
+ ++count;
+ }
+ }
+
+ EXPECT_EQ(1, count);
+
+ android_logger_list_close(logger_list);
+}
+
+TEST(libc, __libc_fatal_no_abort) {
+ struct logger_list *logger_list;
+
+ pid_t pid = getpid();
+
+ ASSERT_TRUE(NULL != (logger_list = android_logger_list_open(
+ (log_id_t)LOG_ID_MAIN, O_RDONLY | O_NDELAY, 1000, pid)));
+
+ char b[80];
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+
+ __libc_fatal_no_abort("%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
+ snprintf(b, sizeof(b),"%u.%09u", (unsigned)ts.tv_sec, (unsigned)ts.tv_nsec);
+ usleep(1000000);
+
+ int count = 0;
+
+ for (;;) {
+ log_msg log_msg;
+ if (android_logger_list_read(logger_list, &log_msg) <= 0) {
+ break;
+ }
+
+ ASSERT_EQ(log_msg.entry.pid, pid);
+
+ if ((int)log_msg.id() != LOG_ID_MAIN) {
+ continue;
+ }
+
+ char *data = log_msg.msg();
+
+ if ((*data == ANDROID_LOG_FATAL)
+ && !strcmp(data + 1, "libc")
+ && !strcmp(data + 1 + strlen(data + 1) + 1, b)) {
+ ++count;
+ }
+ }
+
+ EXPECT_EQ(1, count);
+
+ android_logger_list_close(logger_list);
+}
diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp
index 8dcab87..38a237c 100644
--- a/logd/LogBuffer.cpp
+++ b/logd/LogBuffer.cpp
@@ -167,17 +167,14 @@
if ((id != LOG_ID_CRASH) && mPrune.worstUidEnabled()) {
LidStatistics &l = stats.id(id);
- UidStatisticsCollection::iterator iu;
- for (iu = l.begin(); iu != l.end(); ++iu) {
- UidStatistics *u = (*iu);
- size_t sizes = u->sizes();
- if (worst_sizes < sizes) {
- second_worst_sizes = worst_sizes;
- worst_sizes = sizes;
- worst = u->getUid();
- }
- if ((second_worst_sizes < sizes) && (sizes < worst_sizes)) {
- second_worst_sizes = sizes;
+ l.sort();
+ UidStatisticsCollection::iterator iu = l.begin();
+ if (iu != l.end()) {
+ UidStatistics *u = *iu;
+ worst = u->getUid();
+ worst_sizes = u->sizes();
+ if (++iu != l.end()) {
+ second_worst_sizes = (*iu)->sizes();
}
}
}
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 5146030..f44f567 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -96,7 +96,9 @@
}
UidStatistics::UidStatistics(uid_t uid)
- : uid(uid) {
+ : uid(uid)
+ , mSizes(0)
+ , mElements(0) {
Pids.clear();
}
@@ -109,6 +111,9 @@
}
void UidStatistics::add(unsigned short size, pid_t pid) {
+ mSizes += size;
+ ++mElements;
+
PidStatistics *p;
PidStatisticsCollection::iterator last;
PidStatisticsCollection::iterator it;
@@ -116,18 +121,11 @@
p = *it;
if (pid == p->getPid()) {
p->add(size);
- // poor-man sort, bubble upwards if bigger than last
- if ((last != it) && ((*last)->sizesTotal() < p->sizesTotal())) {
- Pids.erase(it);
- Pids.insert(last, p);
- }
return;
}
}
- // poor-man sort, insert if bigger than last or last is the gone entry.
- bool insert = (last != it)
- && ((p->getPid() == p->gone)
- || ((*last)->sizesTotal() < (size_t) size));
+ // insert if the gone entry.
+ bool insert = (last != it) && (p->getPid() == p->gone);
p = new PidStatistics(pid, pidToName(pid));
if (insert) {
Pids.insert(last, p);
@@ -138,6 +136,9 @@
}
void UidStatistics::subtract(unsigned short size, pid_t pid) {
+ mSizes -= size;
+ --mElements;
+
PidStatisticsCollection::iterator it;
for (it = begin(); it != end(); ++it) {
PidStatistics *p = *it;
@@ -166,28 +167,57 @@
}
}
+void UidStatistics::sort() {
+ for (bool pass = true; pass;) {
+ pass = false;
+ PidStatisticsCollection::iterator it = begin();
+ if (it != end()) {
+ PidStatisticsCollection::iterator lt = it;
+ PidStatistics *l = (*lt);
+ while (++it != end()) {
+ PidStatistics *n = (*it);
+ if ((n->getPid() != n->gone) && (n->sizes() > l->sizes())) {
+ pass = true;
+ Pids.erase(it);
+ Pids.insert(lt, n);
+ it = lt;
+ n = l;
+ }
+ lt = it;
+ l = n;
+ }
+ }
+ }
+}
+
size_t UidStatistics::sizes(pid_t pid) {
- size_t sizes = 0;
+ if (pid == pid_all) {
+ return sizes();
+ }
+
PidStatisticsCollection::iterator it;
for (it = begin(); it != end(); ++it) {
PidStatistics *p = *it;
- if ((pid == pid_all) || (pid == p->getPid())) {
- sizes += p->sizes();
+ if (pid == p->getPid()) {
+ return p->sizes();
}
}
- return sizes;
+ return 0;
}
size_t UidStatistics::elements(pid_t pid) {
- size_t elements = 0;
+ if (pid == pid_all) {
+ return elements();
+ }
+
PidStatisticsCollection::iterator it;
for (it = begin(); it != end(); ++it) {
PidStatistics *p = *it;
- if ((pid == pid_all) || (pid == p->getPid())) {
- elements += p->elements();
+ if (pid == p->getPid()) {
+ return p->elements();
}
}
- return elements;
+ return 0;
}
size_t UidStatistics::sizesTotal(pid_t pid) {
@@ -266,6 +296,29 @@
}
}
+void LidStatistics::sort() {
+ for (bool pass = true; pass;) {
+ pass = false;
+ UidStatisticsCollection::iterator it = begin();
+ if (it != end()) {
+ UidStatisticsCollection::iterator lt = it;
+ UidStatistics *l = (*lt);
+ while (++it != end()) {
+ UidStatistics *n = (*it);
+ if (n->sizes() > l->sizes()) {
+ pass = true;
+ Uids.erase(it);
+ Uids.insert(lt, n);
+ it = lt;
+ n = l;
+ }
+ lt = it;
+ l = n;
+ }
+ }
+ }
+}
+
size_t LidStatistics::sizes(uid_t uid, pid_t pid) {
size_t sizes = 0;
UidStatisticsCollection::iterator it;
@@ -455,13 +508,22 @@
short spaces = 2;
log_id_for_each(i) {
- if (logMask & (1 << i)) {
- oldLength = string.length();
- if (spaces < 0) {
- spaces = 0;
- }
- string.appendFormat("%*s%s", spaces, "", android_log_id_to_name(i));
- spaces += spaces_total + oldLength - string.length();
+ if (!logMask & (1 << i)) {
+ continue;
+ }
+ oldLength = string.length();
+ if (spaces < 0) {
+ spaces = 0;
+ }
+ string.appendFormat("%*s%s", spaces, "", android_log_id_to_name(i));
+ spaces += spaces_total + oldLength - string.length();
+
+ LidStatistics &l = id(i);
+ l.sort();
+
+ UidStatisticsCollection::iterator iu;
+ for (iu = l.begin(); iu != l.end(); ++iu) {
+ (*iu)->sort();
}
}
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index 12c68d5..cd6ef7b 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -70,6 +70,9 @@
PidStatisticsCollection Pids;
+ size_t mSizes;
+ size_t mElements;
+
public:
UidStatistics(uid_t uid);
~UidStatistics();
@@ -81,11 +84,17 @@
void add(unsigned short size, pid_t pid);
void subtract(unsigned short size, pid_t pid);
+ void sort();
static const pid_t pid_all = (pid_t) -1;
- size_t sizes(pid_t pid = pid_all);
- size_t elements(pid_t pid = pid_all);
+ // fast track current value
+ size_t sizes() const { return mSizes; };
+ size_t elements() const { return mElements; };
+
+ // statistical track
+ size_t sizes(pid_t pid);
+ size_t elements(pid_t pid);
size_t sizesTotal(pid_t pid = pid_all);
size_t elementsTotal(pid_t pid = pid_all);
@@ -108,6 +117,7 @@
void add(unsigned short size, uid_t uid, pid_t pid);
void subtract(unsigned short size, uid_t uid, pid_t pid);
+ void sort();
static const pid_t pid_all = (pid_t) -1;
static const uid_t uid_all = (uid_t) -1;
@@ -145,6 +155,7 @@
void add(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
void subtract(unsigned short size, log_id_t log_id, uid_t uid, pid_t pid);
+ void sort();
// fast track current value by id only
size_t sizes(log_id_t id) const { return mSizes[id]; }
diff --git a/logd/LogWhiteBlackList.cpp b/logd/LogWhiteBlackList.cpp
index f739865..c6c7b23 100644
--- a/logd/LogWhiteBlackList.cpp
+++ b/logd/LogWhiteBlackList.cpp
@@ -47,7 +47,7 @@
}
PruneList::PruneList()
- : mWorstUidEnabled(false) {
+ : mWorstUidEnabled(true) {
mNaughty.clear();
mNice.clear();
}
diff --git a/logd/tests/logd_test.cpp b/logd/tests/logd_test.cpp
index 23e6146..731aff6 100644
--- a/logd/tests/logd_test.cpp
+++ b/logd/tests/logd_test.cpp
@@ -23,6 +23,7 @@
#include <gtest/gtest.h>
#include "cutils/sockets.h"
+#include "log/log.h"
#include "log/logger.h"
#define __unused __attribute__((__unused__))
@@ -96,8 +97,9 @@
//
// main: UID/PID Total size/num Now UID/PID[?] Total
// 0 7500306/304207 71608/3183 0/4225? 7454388/303656
+ // <wrap> 93432/1012
// -or-
- // 0/gone 7454388/303656
+ // 0/gone 7454388/303656 93432/1012
//
// basically if we see a *large* number of 0/????? entries
unsigned long value;
@@ -126,6 +128,15 @@
value = value * 10ULL + *cp - '0';
++cp;
}
+ if (*cp != '/') {
+ value = 0;
+ continue;
+ }
+ while (isdigit(*++cp));
+ while (*cp == ' ') ++cp;
+ if (!isdigit(*cp)) {
+ value = 0;
+ }
}
} while ((value < 900000ULL) && *cp);
return cp;
@@ -624,7 +635,45 @@
#endif
ASSERT_TRUE(NULL != buf);
- EXPECT_TRUE(find_benchmark_spam(buf) != NULL);
+
+ char *benchmark_statistics_found = find_benchmark_spam(buf);
+ ASSERT_TRUE(benchmark_statistics_found != NULL);
+
+ // Check how effective the SPAM filter is, parse out Now size.
+ // Total Now
+ // 0/4225? 7454388/303656 31488/755
+ // ^-- benchmark_statistics_found
+
+ unsigned long nowSize = atol(benchmark_statistics_found);
delete [] buf;
+
+ ASSERT_NE(0UL, nowSize);
+
+ int sock = socket_local_client("logd",
+ ANDROID_SOCKET_NAMESPACE_RESERVED,
+ SOCK_STREAM);
+ static const unsigned long expected_absolute_minimum_log_size = 65536UL;
+ unsigned long totalSize = expected_absolute_minimum_log_size;
+ if (sock >= 0) {
+ static const char getSize[] = {
+ 'g', 'e', 't', 'L', 'o', 'g', 'S', 'i', 'z', 'e', ' ',
+ LOG_ID_MAIN + '0', '\0'
+ };
+ if (write(sock, getSize, sizeof(getSize)) > 0) {
+ char buffer[80];
+ memset(buffer, 0, sizeof(buffer));
+ read(sock, buffer, sizeof(buffer));
+ totalSize = atol(buffer);
+ if (totalSize < expected_absolute_minimum_log_size) {
+ totalSize = expected_absolute_minimum_log_size;
+ }
+ }
+ close(sock);
+ }
+ // logd allows excursions to 110% of total size
+ totalSize = (totalSize * 11 ) / 10;
+
+ // 50% threshold for SPAM filter (<20% typical, lots of engineering margin)
+ ASSERT_GT(totalSize, nowSize * 2);
}