diff --git a/liblog/log_read.c b/liblog/log_read.c index eb44b2942..1aff272f7 100644 --- a/liblog/log_read.c +++ b/liblog/log_read.c @@ -501,6 +501,14 @@ ssize_t android_logger_get_statistics(struct logger_list *logger_list, remaining -= n; cp += n; } + + if (logger_list->pid) { + n = snprintf(cp, remaining, " pid=%u", logger_list->pid); + n = min(n, remaining); + remaining -= n; + cp += n; + } + return send_log_msg(NULL, NULL, buf, len); } diff --git a/logd/CommandListener.cpp b/logd/CommandListener.cpp index e10335916..7394f1140 100644 --- a/logd/CommandListener.cpp +++ b/logd/CommandListener.cpp @@ -210,9 +210,20 @@ int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli, } unsigned int logMask = -1; + pid_t pid = 0; if (argc > 1) { logMask = 0; for (int i = 1; i < argc; ++i) { + static const char _pid[] = "pid="; + if (!strncmp(argv[i], _pid, sizeof(_pid) - 1)) { + pid = atol(argv[i] + sizeof(_pid) - 1); + if (pid == 0) { + cli->sendMsg("PID Error"); + return 0; + } + continue; + } + int id = atoi(argv[i]); if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) { cli->sendMsg("Range Error"); @@ -222,7 +233,8 @@ int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli, } } - cli->sendMsg(package_string(mBuf.formatStatistics(uid, logMask)).c_str()); + cli->sendMsg(package_string(mBuf.formatStatistics(uid, pid, + logMask)).c_str()); return 0; } diff --git a/logd/LogBuffer.cpp b/logd/LogBuffer.cpp index 5922f16e6..12aa84e27 100644 --- a/logd/LogBuffer.cpp +++ b/logd/LogBuffer.cpp @@ -499,7 +499,8 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) { size_t second_worst_sizes = 0; if (worstUidEnabledForLogid(id) && mPrune.worstUidEnabled()) { - std::unique_ptr sorted = stats.sort(2, id); + std::unique_ptr sorted = stats.sort( + AID_ROOT, (pid_t)0, 2, id); if (sorted.get()) { if (sorted[0] && sorted[1]) { @@ -866,10 +867,11 @@ uint64_t LogBuffer::flushTo( return max; } -std::string LogBuffer::formatStatistics(uid_t uid, unsigned int logMask) { +std::string LogBuffer::formatStatistics(uid_t uid, pid_t pid, + unsigned int logMask) { pthread_mutex_lock(&mLogElementsLock); - std::string ret = stats.format(uid, logMask); + std::string ret = stats.format(uid, pid, logMask); pthread_mutex_unlock(&mLogElementsLock); diff --git a/logd/LogBuffer.h b/logd/LogBuffer.h index c1fec73bb..c1614e847 100644 --- a/logd/LogBuffer.h +++ b/logd/LogBuffer.h @@ -86,7 +86,7 @@ public: int setSize(log_id_t id, unsigned long size); unsigned long getSizeUsed(log_id_t id); // *strp uses malloc, use free to release. - std::string formatStatistics(uid_t uid, unsigned int logMask); + std::string formatStatistics(uid_t uid, pid_t pid, unsigned int logMask); void enableStatistics() { stats.enableStatistics(); diff --git a/logd/LogStatistics.cpp b/logd/LogStatistics.cpp index bf0e30b09..afaefc25f 100644 --- a/logd/LogStatistics.cpp +++ b/logd/LogStatistics.cpp @@ -205,7 +205,7 @@ std::string UidEntry::formatHeader(const std::string &name, log_id_t id) const { } std::string UidEntry::format(const LogStatistics &stat, log_id_t id) const { - uid_t uid = getKey(); + uid_t uid = getUid(); std::string name = android::base::StringPrintf("%u", uid); const char *nameTmp = stat.uidToName(uid); if (nameTmp) { @@ -287,8 +287,8 @@ std::string PidEntry::formatHeader(const std::string &name, log_id_t /* id */) c std::string PidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getUid(); - std::string name = android::base::StringPrintf("%5u/%u", - getKey(), uid); + pid_t pid = getPid(); + std::string name = android::base::StringPrintf("%5u/%u", pid, uid); const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( @@ -325,7 +325,7 @@ std::string TidEntry::formatHeader(const std::string &name, log_id_t /* id */) c std::string TidEntry::format(const LogStatistics &stat, log_id_t /* id */) const { uid_t uid = getUid(); std::string name = android::base::StringPrintf("%5u/%u", - getKey(), uid); + getTid(), uid); const char *nameTmp = getName(); if (nameTmp) { name += android::base::StringPrintf( @@ -388,7 +388,8 @@ std::string TagEntry::format(const LogStatistics & /* stat */, log_id_t /* id */ return formatLine(name, size, pruned); } -std::string LogStatistics::format(uid_t uid, unsigned int logMask) const { +std::string LogStatistics::format(uid_t uid, pid_t pid, + unsigned int logMask) const { static const unsigned short spaces_total = 19; // Report on total logging, current and for all time @@ -461,24 +462,38 @@ std::string LogStatistics::format(uid_t uid, unsigned int logMask) const { name = (uid == AID_ROOT) ? "Chattiest UIDs in %s log buffer:" : "Logging for your UID in %s log buffer:"; - output += uidTable[id].format(*this, uid, name, id); + output += uidTable[id].format(*this, uid, pid, name, id); } if (enable) { - name = (uid == AID_ROOT) ? "Chattiest PIDs:" : "Logging for this PID:"; - output += pidTable.format(*this, uid, name); - name = "Chattiest TIDs:"; - output += tidTable.format(*this, uid, name); + name = ((uid == AID_ROOT) && !pid) + ? "Chattiest PIDs:" + : "Logging for this PID:"; + output += pidTable.format(*this, uid, pid, name); + name = "Chattiest TIDs"; + if (pid) { + name += android::base::StringPrintf(" for PID %d", pid); + } + name += ":"; + output += tidTable.format(*this, uid, pid, name); } if (enable && (logMask & (1 << LOG_ID_EVENTS))) { - name = "Chattiest events log buffer TAGs:"; - output += tagTable.format(*this, uid, name, LOG_ID_EVENTS); + name = "Chattiest events log buffer TAGs"; + if (pid) { + name += android::base::StringPrintf(" for PID %d", pid); + } + name += ":"; + output += tagTable.format(*this, uid, pid, name, LOG_ID_EVENTS); } if (enable && (logMask & (1 << LOG_ID_SECURITY))) { - name = "Chattiest security log buffer TAGs:"; - output += securityTagTable.format(*this, uid, name, LOG_ID_SECURITY); + name = "Chattiest security log buffer TAGs"; + if (pid) { + name += android::base::StringPrintf(" for PID %d", pid); + } + name += ":"; + output += securityTagTable.format(*this, uid, pid, name, LOG_ID_SECURITY); } return output; diff --git a/logd/LogStatistics.h b/logd/LogStatistics.h index 8558b0671..6d999d229 100644 --- a/logd/LogStatistics.h +++ b/logd/LogStatistics.h @@ -47,7 +47,8 @@ public: typedef typename std::unordered_map::iterator iterator; typedef typename std::unordered_map::const_iterator const_iterator; - std::unique_ptr sort(size_t len) const { + std::unique_ptr sort(uid_t uid, pid_t pid, + size_t len) const { if (!len) { std::unique_ptr sorted(NULL); return sorted; @@ -58,6 +59,14 @@ public: for(const_iterator it = map.begin(); it != map.end(); ++it) { const TEntry &entry = it->second; + + if ((uid != AID_ROOT) && (uid != entry.getUid())) { + continue; + } + if (pid && entry.getPid() && (pid != entry.getPid())) { + continue; + } + size_t sizes = entry.getSizes(); ssize_t index = len - 1; while ((!retval[index] || (sizes > retval[index]->getSizes())) @@ -118,12 +127,13 @@ public: std::string format( const LogStatistics &stat, uid_t uid, + pid_t pid, const std::string &name = std::string(""), log_id_t id = LOG_ID_MAX) const { static const size_t maximum_sorted_entries = 32; std::string output; - std::unique_ptr sorted = sort(maximum_sorted_entries); - + std::unique_ptr sorted = sort(uid, pid, + maximum_sorted_entries); if (!sorted.get()) { return output; } @@ -136,9 +146,6 @@ public: if (entry->getSizes() <= (sorted[0]->getSizes() / 100)) { break; } - if ((uid != AID_ROOT) && (uid != entry->getUid())) { - continue; - } if (!headerPrinted) { output += "\n\n"; output += entry->formatHeader(name, id); @@ -217,14 +224,24 @@ struct EntryBaseDropped : public EntryBase { struct UidEntry : public EntryBaseDropped { const uid_t uid; + pid_t pid; UidEntry(LogBufferElement *element): EntryBaseDropped(element), - uid(element->getUid()) { + uid(element->getUid()), + pid(element->getPid()) { } inline const uid_t&getKey() const { return uid; } - inline const uid_t&getUid() const { return uid; } + inline const uid_t&getUid() const { return getKey(); } + inline const pid_t&getPid() const { return pid; } + + inline void add(LogBufferElement *element) { + if (pid != element->getPid()) { + pid = -1; + } + 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; @@ -260,6 +277,7 @@ struct PidEntry : public EntryBaseDropped { ~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; } @@ -291,30 +309,36 @@ struct PidEntry : public EntryBaseDropped { struct TidEntry : public EntryBaseDropped { const pid_t tid; + pid_t pid; uid_t uid; char *name; - TidEntry(pid_t tid): + TidEntry(pid_t tid, pid_t pid): EntryBaseDropped(), tid(tid), + pid(pid), uid(android::pidToUid(tid)), name(android::tidToName(tid)) { } TidEntry(LogBufferElement *element): EntryBaseDropped(element), tid(element->getTid()), + pid(element->getPid()), uid(element->getUid()), 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) : NULL) { } ~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; } @@ -330,8 +354,10 @@ struct TidEntry : public EntryBaseDropped { inline void add(LogBufferElement *element) { uid_t incomingUid = element->getUid(); - if (getUid() != incomingUid) { + pid_t incomingPid = element->getPid(); + if ((getUid() != incomingUid) || (getPid() != incomingPid)) { uid = incomingUid; + pid = incomingPid; free(name); name = android::tidToName(element->getTid()); } else { @@ -346,23 +372,28 @@ struct TidEntry : public EntryBaseDropped { struct TagEntry : public EntryBase { const uint32_t tag; + pid_t pid; uid_t uid; TagEntry(LogBufferElement *element): EntryBase(element), tag(element->getTag()), + pid(element->getPid()), uid(element->getUid()) { } 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); } inline void add(LogBufferElement *element) { - uid_t incomingUid = element->getUid(); - if (uid != incomingUid) { + if (uid != element->getUid()) { uid = -1; } + if (pid != element->getPid()) { + pid = -1; + } EntryBase::add(element); } @@ -416,8 +447,9 @@ public: --mDroppedElements[log_id]; } - std::unique_ptr sort(size_t len, log_id id) { - return uidTable[id].sort(len); + std::unique_ptr sort(uid_t uid, pid_t pid, + size_t len, log_id id) { + return uidTable[id].sort(uid, pid, len); } // fast track current value by id only @@ -429,7 +461,7 @@ public: size_t sizesTotal(log_id_t id) const { return mSizesTotal[id]; } size_t elementsTotal(log_id_t id) const { return mElementsTotal[id]; } - std::string format(uid_t uid, unsigned int logMask) const; + std::string format(uid_t uid, pid_t pid, unsigned int logMask) const; // helper (must be locked directly or implicitly by mLogElementsLock) const char *pidToName(pid_t pid) const;