Merge changes Ic446c026,I86568a5b
* changes:
init: create init_tests.cpp
init: clean up the SectionParser interface and Parser class
diff --git a/libcutils/fs_config.c b/libcutils/fs_config.c
index 5fc2386..6e5db0b 100644
--- a/libcutils/fs_config.c
+++ b/libcutils/fs_config.c
@@ -158,7 +158,6 @@
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" },
{ 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" },
{ 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" },
- { 00440, AID_RADIO, AID_ROOT, 0, "system/etc/xtables.lock" },
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" },
{ 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" },
{ 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 },
diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp
index 0b6b28c..594bd0d 100644
--- a/logd/LogStatistics.cpp
+++ b/logd/LogStatistics.cpp
@@ -32,6 +32,7 @@
static const uint64_t monthSec = 31 * 24 * hourSec;
size_t LogStatistics::SizesTotal;
+size_t TagNameEntry::droppedElsewhere;
LogStatistics::LogStatistics() : enable(false) {
log_time now(CLOCK_REALTIME);
@@ -152,6 +153,8 @@
tagTable.add(tag, element);
}
}
+
+ tagNameTable.add(TagNameEntry(element).getKey(), element);
}
void LogStatistics::subtract(LogBufferElement* element) {
@@ -191,6 +194,8 @@
tagTable.subtract(tag, element);
}
}
+
+ tagNameTable.subtract(TagNameEntry(element).getKey(), element);
}
// Atomically set an entry to drop
@@ -225,6 +230,8 @@
tagTable.drop(tag, element);
}
}
+
+ tagNameTable.drop(TagNameEntry(element).getKey(), element);
}
// caller must own and free character string
@@ -505,6 +512,71 @@
return formatLine(name, size, pruned);
}
+std::string TagNameEntry::formatHeader(const std::string& name,
+ log_id_t /* id */) const {
+ return formatLine(name, std::string("Size"), std::string("Prune")) +
+ formatLine(std::string(" TID/PID/UID LOG_TAG NAME"),
+ std::string("BYTES"), std::string("NUM"));
+}
+
+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;
+ }
+ int len = 9 - pidstr.length();
+ if (len < 0) len = 0;
+ if ((tid == (pid_t)-1) || (tid == pid)) {
+ name = android::base::StringPrintf("%*s", len, "");
+ } else {
+ name = android::base::StringPrintf("%*u", len, tid);
+ }
+ name += pidstr;
+ uid_t uid = getUid();
+ if (uid != (uid_t)-1) {
+ name += android::base::StringPrintf("/%u", uid);
+ }
+
+ std::string size = android::base::StringPrintf("%zu", getSizes());
+
+ const char* nameTmp = getName();
+ 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 lenNameTmp = strlen(nameTmp);
+ while ((len < lenNameTmp) && (lenSpace > 1)) {
+ ++len;
+ --lenSpace;
+ }
+ name += android::base::StringPrintf("%*s", (int)lenSpace, "");
+ if (len < lenNameTmp) {
+ name += "...";
+ nameTmp += lenNameTmp - std::max(len - 3, (size_t)1);
+ }
+ name += nameTmp;
+ }
+
+ std::string pruned = "";
+
+ // Because of TagNameEntry::droppedElsewhere, dropped count can get
+ // modified for "chatty" tags. Since the size is always zero this
+ // modification is a "can not happen".
+ TagNameEntry& me = const_cast<TagNameEntry&>(*this);
+ size_t dropped = me.getDropped();
+ if (dropped) {
+ pruned = android::base::StringPrintf("%zu", dropped);
+ }
+
+ return formatLine(name, size, pruned);
+}
+
static std::string formatMsec(uint64_t val) {
static const unsigned subsecDigits = 3;
static const uint64_t sec = MS_PER_SEC;
@@ -725,6 +797,13 @@
output += tidTable.format(*this, uid, pid, name);
}
+ if (enable) {
+ name = "Chattiest TAGs";
+ if (pid) name += android::base::StringPrintf(" for PID %d", pid);
+ name += ":";
+ output += tagNameTable.format(*this, uid, pid, name);
+ }
+
if (enable && (logMask & (1 << LOG_ID_EVENTS))) {
name = "Chattiest events log buffer TAGs";
if (pid) name += android::base::StringPrintf(" for PID %d", pid);
diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h
index e6f01d6..84dbff3 100644
--- a/logd/LogStatistics.h
+++ b/logd/LogStatistics.h
@@ -18,10 +18,14 @@
#define _LOGD_LOG_STATISTICS_H__
#include <ctype.h>
+#include <inttypes.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/types.h>
#include <algorithm> // std::max
+#include <experimental/string_view>
#include <memory>
#include <string> // std::string
#include <unordered_map>
@@ -77,7 +81,7 @@
std::unique_ptr<const TEntry* []> sort(uid_t uid, pid_t pid,
size_t len) const {
if (!len) {
- std::unique_ptr<const TEntry* []> sorted(NULL);
+ std::unique_ptr<const TEntry* []> sorted(nullptr);
return sorted;
}
@@ -318,7 +322,7 @@
: EntryBaseDropped(element),
pid(element.pid),
uid(element.uid),
- name(element.name ? strdup(element.name) : NULL) {
+ name(element.name ? strdup(element.name) : nullptr) {
}
~PidEntry() {
free(name);
@@ -340,7 +344,7 @@
inline void add(pid_t newPid) {
if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
free(name);
- name = NULL;
+ name = nullptr;
}
if (!name) {
name = android::pidToName(newPid);
@@ -388,7 +392,7 @@
tid(element.tid),
pid(element.pid),
uid(element.uid),
- name(element.name ? strdup(element.name) : NULL) {
+ name(element.name ? strdup(element.name) : nullptr) {
}
~TidEntry() {
free(name);
@@ -413,7 +417,7 @@
inline void add(pid_t incomingTid) {
if (name && !fastcmp<strncmp>(name, "zygote", 6)) {
free(name);
- name = NULL;
+ name = nullptr;
}
if (!name) {
name = android::tidToName(incomingTid);
@@ -477,6 +481,141 @@
std::string format(const LogStatistics& stat, log_id_t id) const;
};
+struct TagNameEntry : public EntryBaseDropped {
+ // We do not care that a dropped entry does, or does not exist, because
+ // the size will always report zero. But if it does, we need to account
+ // for the ones that transitioned from a known tag to chatty so that we
+ // do not spring a leak on the dropped counts.
+ static size_t droppedElsewhere;
+
+ pid_t tid;
+ pid_t pid;
+ uid_t uid;
+ std::string* alloc;
+ std::experimental::string_view name; // Saves space if const char*
+
+ explicit TagNameEntry(LogBufferElement* element)
+ : EntryBaseDropped(element),
+ tid(element->getTid()),
+ pid(element->getPid()),
+ uid(element->getUid()),
+ alloc(nullptr) {
+ if (element->isBinary()) {
+ uint32_t tag = element->getTag();
+ if (tag) {
+ const char* cp = android::tagToName(tag);
+ if (cp) {
+ name = std::experimental::string_view(cp, strlen(cp));
+ return;
+ }
+ }
+ alloc = new std::string(
+ android::base::StringPrintf("[%" PRIu32 "]", tag));
+ if (!alloc) return;
+ name = std::experimental::string_view(alloc->c_str(), alloc->size());
+ return;
+ }
+ const char* msg = element->getMsg();
+ if (!msg) {
+ name = std::experimental::string_view("chatty", strlen("chatty"));
+ return;
+ }
+ ++msg;
+ unsigned short len = element->getMsgLen();
+ len = (len <= 1) ? 0 : strnlen(msg, len - 1);
+ if (!len) {
+ name = std::experimental::string_view("<NULL>", strlen("<NULL>"));
+ return;
+ }
+ alloc = new std::string(msg, len);
+ if (!alloc) return;
+ name = std::experimental::string_view(alloc->c_str(), alloc->size());
+ }
+
+ explicit TagNameEntry(TagNameEntry&& rval)
+ : tid(rval.tid),
+ pid(rval.pid),
+ uid(rval.uid),
+ alloc(rval.alloc),
+ name(rval.name.data(), rval.name.length()) {
+ rval.alloc = nullptr;
+ }
+
+ explicit TagNameEntry(const TagNameEntry& rval)
+ : tid(rval.tid),
+ pid(rval.pid),
+ uid(rval.uid),
+ alloc(rval.alloc ? new std::string(*rval.alloc) : nullptr),
+ name(alloc ? alloc->data() : rval.name.data(), rval.name.length()) {
+ }
+
+ ~TagNameEntry() {
+ if (alloc) delete alloc;
+ }
+
+ const std::experimental::string_view& 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 alloc ? alloc->length() + 1 : 0;
+ }
+
+ size_t getDropped() {
+ if (__predict_false(name == "chatty")) { // plug the leak
+ dropped += droppedElsewhere;
+ droppedElsewhere = 0;
+ }
+ return EntryBaseDropped::getDropped();
+ }
+
+ inline void add(LogBufferElement* element) {
+ if (uid != element->getUid()) {
+ uid = -1;
+ }
+ if (pid != element->getPid()) {
+ pid = -1;
+ }
+ if (tid != element->getTid()) {
+ tid = -1;
+ }
+ // Fixup of dropped can be deferred.
+ EntryBaseDropped::add(element);
+ }
+
+ inline bool subtract(LogBufferElement* element) {
+ if (__predict_false(name == "chatty")) { // plug the leak
+ dropped += droppedElsewhere;
+ droppedElsewhere = 0;
+ }
+ return EntryBaseDropped::subtract(element);
+ }
+
+ inline void drop(LogBufferElement* element) {
+ if (__predict_false(name == "chatty")) { // plug the leak
+ dropped += droppedElsewhere;
+ droppedElsewhere = 0;
+ } else {
+ ++droppedElsewhere;
+ }
+ return EntryBaseDropped::drop(element);
+ }
+
+ std::string formatHeader(const std::string& name, log_id_t id) const;
+ std::string format(const LogStatistics& stat, log_id_t id) const;
+};
+
template <typename TEntry>
class LogFindWorst {
std::unique_ptr<const TEntry* []> sorted;
@@ -550,9 +689,15 @@
// security tag list
tagTable_t securityTagTable;
+ // global tag list
+ typedef LogHashtable<std::experimental::string_view, TagNameEntry>
+ tagNameTable_t;
+ tagNameTable_t tagNameTable;
+
size_t sizeOf() const {
size_t size = sizeof(*this) + pidTable.sizeOf() + tidTable.sizeOf() +
tagTable.sizeOf() + securityTagTable.sizeOf() +
+ tagNameTable.sizeOf() +
(pidTable.size() * sizeof(pidTable_t::iterator)) +
(tagTable.size() * sizeof(tagTable_t::iterator));
for (auto it : pidTable) {
@@ -563,6 +708,7 @@
const char* name = it.second.getName();
if (name) size += strlen(name) + 1;
}
+ for (auto it : tagNameTable) size += it.second.getNameAllocLength();
log_id_for_each(id) {
size += uidTable[id].sizeOf();
size += uidTable[id].size() * sizeof(uidTable_t::iterator);