logd: make LogBuffer an interface
We may use different implementations of LogBuffer in the future, so we make it interface and create a concrete ChattyLogBuffer class that implements it. Test: logging unit tests Change-Id: I5731d6404640664c9acc26b7c677dff3110c6a11
This commit is contained in:
parent
68630a0dbe
commit
d5b3838dbc
|
@ -33,12 +33,12 @@ cc_library_static {
|
|||
|
||||
srcs: [
|
||||
"LogCommand.cpp",
|
||||
"ChattyLogBuffer.cpp",
|
||||
"CommandListener.cpp",
|
||||
"LogListener.cpp",
|
||||
"LogReader.cpp",
|
||||
"LogReaderList.cpp",
|
||||
"LogReaderThread.cpp",
|
||||
"LogBuffer.cpp",
|
||||
"LogBufferElement.cpp",
|
||||
"LogStatistics.cpp",
|
||||
"LogWhiteBlackList.cpp",
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
// for manual checking of stale entries during LogBuffer::erase()
|
||||
// for manual checking of stale entries during ChattyLogBuffer::erase()
|
||||
//#define DEBUG_CHECK_FOR_STALE_ENTRIES
|
||||
|
||||
#include "ChattyLogBuffer.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
|
@ -32,7 +34,6 @@
|
|||
#include <cutils/properties.h>
|
||||
#include <private/android_logger.h>
|
||||
|
||||
#include "LogBuffer.h"
|
||||
#include "LogKlog.h"
|
||||
#include "LogReader.h"
|
||||
#include "LogUtils.h"
|
||||
|
@ -44,10 +45,10 @@
|
|||
// Default
|
||||
#define log_buffer_size(id) mMaxSize[id]
|
||||
|
||||
void LogBuffer::init() {
|
||||
void ChattyLogBuffer::Init() {
|
||||
log_id_for_each(i) {
|
||||
if (setSize(i, __android_logger_get_buffer_size(i))) {
|
||||
setSize(i, LOG_BUFFER_MIN_SIZE);
|
||||
if (SetSize(i, __android_logger_get_buffer_size(i))) {
|
||||
SetSize(i, LOG_BUFFER_MIN_SIZE);
|
||||
}
|
||||
}
|
||||
// Release any sleeping reader threads to dump their current content.
|
||||
|
@ -57,8 +58,8 @@ void LogBuffer::init() {
|
|||
}
|
||||
}
|
||||
|
||||
LogBuffer::LogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune,
|
||||
LogStatistics* stats)
|
||||
ChattyLogBuffer::ChattyLogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune,
|
||||
LogStatistics* stats)
|
||||
: reader_list_(reader_list), tags_(tags), prune_(prune), stats_(stats) {
|
||||
pthread_rwlock_init(&mLogElementsLock, nullptr);
|
||||
|
||||
|
@ -67,17 +68,17 @@ LogBuffer::LogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune
|
|||
droppedElements[i] = nullptr;
|
||||
}
|
||||
|
||||
init();
|
||||
Init();
|
||||
}
|
||||
|
||||
LogBuffer::~LogBuffer() {
|
||||
ChattyLogBuffer::~ChattyLogBuffer() {
|
||||
log_id_for_each(i) {
|
||||
delete lastLoggedElements[i];
|
||||
delete droppedElements[i];
|
||||
}
|
||||
}
|
||||
|
||||
LogBufferElementCollection::iterator LogBuffer::GetOldest(log_id_t log_id) {
|
||||
LogBufferElementCollection::iterator ChattyLogBuffer::GetOldest(log_id_t log_id) {
|
||||
auto it = mLogElements.begin();
|
||||
if (oldest_[log_id]) {
|
||||
it = *oldest_[log_id];
|
||||
|
@ -93,8 +94,7 @@ LogBufferElementCollection::iterator LogBuffer::GetOldest(log_id_t log_id) {
|
|||
|
||||
enum match_type { DIFFERENT, SAME, SAME_LIBLOG };
|
||||
|
||||
static enum match_type identical(LogBufferElement* elem,
|
||||
LogBufferElement* last) {
|
||||
static enum match_type identical(LogBufferElement* elem, LogBufferElement* last) {
|
||||
// is it mostly identical?
|
||||
// if (!elem) return DIFFERENT;
|
||||
ssize_t lenl = elem->getMsgLen();
|
||||
|
@ -108,8 +108,7 @@ static enum match_type identical(LogBufferElement* elem,
|
|||
if (elem->getTid() != last->getTid()) return DIFFERENT;
|
||||
|
||||
// last is more than a minute old, stop squashing identical messages
|
||||
if (elem->getRealTime().nsec() >
|
||||
(last->getRealTime().nsec() + 60 * NS_PER_SEC))
|
||||
if (elem->getRealTime().nsec() > (last->getRealTime().nsec() + 60 * NS_PER_SEC))
|
||||
return DIFFERENT;
|
||||
|
||||
// Identical message
|
||||
|
@ -118,21 +117,17 @@ static enum match_type identical(LogBufferElement* elem,
|
|||
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)) &&
|
||||
!fastcmp<memcmp>(msgl, msgr, sizeof(android_log_event_int_t) -
|
||||
sizeof(int32_t)) &&
|
||||
(elem->getTag() == LIBLOG_LOG_TAG)) {
|
||||
if (elem->getLogId() == 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) {
|
||||
return SAME_LIBLOG;
|
||||
}
|
||||
}
|
||||
|
||||
// audit message (except sequence number) identical?
|
||||
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))) {
|
||||
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;
|
||||
}
|
||||
msgl += sizeof(android_log_event_string_t);
|
||||
|
@ -148,15 +143,14 @@ static enum match_type identical(LogBufferElement* elem,
|
|||
if (!avcr) return DIFFERENT;
|
||||
lenr -= avcr - msgr;
|
||||
if (lenl != lenr) return DIFFERENT;
|
||||
if (fastcmp<memcmp>(avcl + strlen(avc), avcr + strlen(avc),
|
||||
lenl - strlen(avc))) {
|
||||
if (fastcmp<memcmp>(avcl + strlen(avc), avcr + strlen(avc), lenl - strlen(avc))) {
|
||||
return DIFFERENT;
|
||||
}
|
||||
return SAME;
|
||||
}
|
||||
|
||||
int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
|
||||
pid_t tid, const char* msg, uint16_t len) {
|
||||
int ChattyLogBuffer::Log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid, pid_t tid,
|
||||
const char* msg, uint16_t len) {
|
||||
if (log_id >= LOG_ID_MAX) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -278,8 +272,7 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
|
|||
if (dropped) {
|
||||
// Sum up liblog tag messages?
|
||||
if ((count == 0) /* at Pass 1 */ && (match == SAME_LIBLOG)) {
|
||||
android_log_event_int_t* event =
|
||||
reinterpret_cast<android_log_event_int_t*>(
|
||||
android_log_event_int_t* event = reinterpret_cast<android_log_event_int_t*>(
|
||||
const_cast<char*>(currentLast->getMsg()));
|
||||
//
|
||||
// To unit test, differentiate with something like:
|
||||
|
@ -290,7 +283,7 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
|
|||
uint32_t swab = event->payload.data;
|
||||
unsigned long long total = htole32(swab);
|
||||
event = reinterpret_cast<android_log_event_int_t*>(
|
||||
const_cast<char*>(elem->getMsg()));
|
||||
const_cast<char*>(elem->getMsg()));
|
||||
swab = event->payload.data;
|
||||
|
||||
lastLoggedElements[LOG_ID_EVENTS] = elem;
|
||||
|
@ -345,24 +338,24 @@ int LogBuffer::log(log_id_t log_id, log_time realtime, uid_t uid, pid_t pid,
|
|||
return len;
|
||||
}
|
||||
|
||||
// assumes LogBuffer::wrlock() held, owns elem, look after garbage collection
|
||||
void LogBuffer::log(LogBufferElement* elem) {
|
||||
// assumes ChattyLogBuffer::wrlock() held, owns elem, look after garbage collection
|
||||
void ChattyLogBuffer::log(LogBufferElement* elem) {
|
||||
mLogElements.push_back(elem);
|
||||
stats_->Add(elem);
|
||||
maybePrune(elem->getLogId());
|
||||
reader_list_->NotifyNewLog(1 << elem->getLogId());
|
||||
}
|
||||
|
||||
// LogBuffer::wrlock() must be held when this function is called.
|
||||
void LogBuffer::maybePrune(log_id_t id) {
|
||||
// ChattyLogBuffer::wrlock() must be held when this function is called.
|
||||
void ChattyLogBuffer::maybePrune(log_id_t id) {
|
||||
unsigned long prune_rows;
|
||||
if (stats_->ShouldPrune(id, log_buffer_size(id), &prune_rows)) {
|
||||
prune(id, prune_rows);
|
||||
}
|
||||
}
|
||||
|
||||
LogBufferElementCollection::iterator LogBuffer::erase(
|
||||
LogBufferElementCollection::iterator it, bool coalesce) {
|
||||
LogBufferElementCollection::iterator ChattyLogBuffer::erase(LogBufferElementCollection::iterator it,
|
||||
bool coalesce) {
|
||||
LogBufferElement* element = *it;
|
||||
log_id_t id = element->getLogId();
|
||||
|
||||
|
@ -370,9 +363,8 @@ LogBufferElementCollection::iterator LogBuffer::erase(
|
|||
// 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->getUid();
|
||||
LogBufferIteratorMap::iterator found = mLastWorst[id].find(key);
|
||||
if ((found != mLastWorst[id].end()) && (it == found->second)) {
|
||||
mLastWorst[id].erase(found);
|
||||
|
@ -383,10 +375,8 @@ LogBufferElementCollection::iterator LogBuffer::erase(
|
|||
// element->getUid() 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());
|
||||
if ((found != mLastWorstPidOfSystem[id].end()) &&
|
||||
(it == found->second)) {
|
||||
LogBufferPidIteratorMap::iterator found = mLastWorstPidOfSystem[id].find(element->getPid());
|
||||
if (found != mLastWorstPidOfSystem[id].end() && it == found->second) {
|
||||
mLastWorstPidOfSystem[id].erase(found);
|
||||
}
|
||||
}
|
||||
|
@ -396,9 +386,8 @@ LogBufferElementCollection::iterator LogBuffer::erase(
|
|||
log_id_for_each(i) { doSetLast |= setLast[i] = oldest_[i] && it == *oldest_[i]; }
|
||||
#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->getUid();
|
||||
#endif
|
||||
it = mLogElements.erase(it);
|
||||
if (doSetLast) {
|
||||
|
@ -417,14 +406,12 @@ LogBufferElementCollection::iterator LogBuffer::erase(
|
|||
log_id_for_each(i) {
|
||||
for (auto b : mLastWorst[i]) {
|
||||
if (bad == b.second) {
|
||||
android::prdebug("stale mLastWorst[%d] key=%d mykey=%d\n", i,
|
||||
b.first, key);
|
||||
android::prdebug("stale mLastWorst[%d] key=%d mykey=%d\n", i, b.first, key);
|
||||
}
|
||||
}
|
||||
for (auto b : mLastWorstPidOfSystem[i]) {
|
||||
if (bad == b.second) {
|
||||
android::prdebug("stale mLastWorstPidOfSystem[%d] pid=%d\n", i,
|
||||
b.first);
|
||||
android::prdebug("stale mLastWorstPidOfSystem[%d] pid=%d\n", i, b.first);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -452,26 +439,20 @@ class LogBufferElementKey {
|
|||
uint64_t value;
|
||||
} __packed;
|
||||
|
||||
public:
|
||||
LogBufferElementKey(uid_t uid, pid_t pid, pid_t tid)
|
||||
: uid(uid), pid(pid), tid(tid) {
|
||||
}
|
||||
explicit LogBufferElementKey(uint64_t key) : value(key) {
|
||||
}
|
||||
public:
|
||||
LogBufferElementKey(uid_t uid, pid_t pid, pid_t tid) : uid(uid), pid(pid), tid(tid) {}
|
||||
explicit LogBufferElementKey(uint64_t key) : value(key) {}
|
||||
|
||||
uint64_t getKey() {
|
||||
return value;
|
||||
}
|
||||
uint64_t getKey() { return value; }
|
||||
};
|
||||
|
||||
class LogBufferElementLast {
|
||||
typedef std::unordered_map<uint64_t, LogBufferElement*> LogBufferElementMap;
|
||||
LogBufferElementMap map;
|
||||
|
||||
public:
|
||||
public:
|
||||
bool coalesce(LogBufferElement* element, uint16_t dropped) {
|
||||
LogBufferElementKey key(element->getUid(), element->getPid(),
|
||||
element->getTid());
|
||||
LogBufferElementKey key(element->getUid(), element->getPid(), element->getTid());
|
||||
LogBufferElementMap::iterator it = map.find(key.getKey());
|
||||
if (it != map.end()) {
|
||||
LogBufferElement* found = it->second;
|
||||
|
@ -487,14 +468,11 @@ class LogBufferElementLast {
|
|||
}
|
||||
|
||||
void add(LogBufferElement* element) {
|
||||
LogBufferElementKey key(element->getUid(), element->getPid(),
|
||||
element->getTid());
|
||||
LogBufferElementKey key(element->getUid(), element->getPid(), element->getTid());
|
||||
map[key.getKey()] = element;
|
||||
}
|
||||
|
||||
inline void clear() {
|
||||
map.clear();
|
||||
}
|
||||
void clear() { map.clear(); }
|
||||
|
||||
void clear(LogBufferElement* element) {
|
||||
uint64_t current = element->getRealTime().nsec() - (EXPIRE_RATELIMIT * NS_PER_SEC);
|
||||
|
@ -512,11 +490,11 @@ class LogBufferElementLast {
|
|||
|
||||
// If the selected reader is blocking our pruning progress, decide on
|
||||
// what kind of mitigation is necessary to unblock the situation.
|
||||
void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows) {
|
||||
void ChattyLogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows) {
|
||||
if (stats_->Sizes(id) > (2 * log_buffer_size(id))) { // +100%
|
||||
// A misbehaving or slow reader has its connection
|
||||
// dropped if we hit too much memory pressure.
|
||||
android::prdebug("Kicking blocked reader, pid %d, from LogBuffer::kickMe()\n",
|
||||
android::prdebug("Kicking blocked reader, pid %d, from ChattyLogBuffer::kickMe()\n",
|
||||
me->client()->getPid());
|
||||
me->release_Locked();
|
||||
} else if (me->deadline().time_since_epoch().count() != 0) {
|
||||
|
@ -525,7 +503,7 @@ void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows
|
|||
} else {
|
||||
// tell slow reader to skip entries to catch up
|
||||
android::prdebug(
|
||||
"Skipping %lu entries from slow reader, pid %d, from LogBuffer::kickMe()\n",
|
||||
"Skipping %lu entries from slow reader, pid %d, from ChattyLogBuffer::kickMe()\n",
|
||||
pruneRows, me->client()->getPid());
|
||||
me->triggerSkip_Locked(id, pruneRows);
|
||||
}
|
||||
|
@ -576,9 +554,9 @@ void LogBuffer::kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows
|
|||
// The third thread is optional, and only gets hit if there was a whitelist
|
||||
// and more needs to be pruned against the backstop of the region lock.
|
||||
//
|
||||
// LogBuffer::wrlock() must be held when this function is called.
|
||||
// ChattyLogBuffer::wrlock() must be held when this function is called.
|
||||
//
|
||||
bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
||||
bool ChattyLogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
||||
LogReaderThread* oldest = nullptr;
|
||||
bool busy = false;
|
||||
bool clearAll = pruneRows == ULONG_MAX;
|
||||
|
@ -606,8 +584,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
while (it != mLogElements.end()) {
|
||||
LogBufferElement* element = *it;
|
||||
|
||||
if ((element->getLogId() != id) ||
|
||||
(element->getUid() != caller_uid)) {
|
||||
if (element->getLogId() != id || element->getUid() != caller_uid) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
@ -666,10 +643,8 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
bool gc = pruneRows <= 1;
|
||||
if (!gc && (worst != -1)) {
|
||||
{ // begin scope for worst found iterator
|
||||
LogBufferIteratorMap::iterator found =
|
||||
mLastWorst[id].find(worst);
|
||||
if ((found != mLastWorst[id].end()) &&
|
||||
(found->second != mLogElements.end())) {
|
||||
LogBufferIteratorMap::iterator found = mLastWorst[id].find(worst);
|
||||
if (found != mLastWorst[id].end() && found->second != mLogElements.end()) {
|
||||
leading = false;
|
||||
it = found->second;
|
||||
}
|
||||
|
@ -677,10 +652,9 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
if (worstPid) { // begin scope for pid worst found iterator
|
||||
// FYI: worstPid only set if !LOG_ID_EVENTS and
|
||||
// !LOG_ID_SECURITY, not going to make that assumption ...
|
||||
LogBufferPidIteratorMap::iterator found =
|
||||
mLastWorstPidOfSystem[id].find(worstPid);
|
||||
if ((found != mLastWorstPidOfSystem[id].end()) &&
|
||||
(found->second != mLogElements.end())) {
|
||||
LogBufferPidIteratorMap::iterator found = mLastWorstPidOfSystem[id].find(worstPid);
|
||||
if (found != mLastWorstPidOfSystem[id].end() &&
|
||||
found->second != mLogElements.end()) {
|
||||
leading = false;
|
||||
it = found->second;
|
||||
}
|
||||
|
@ -689,7 +663,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
if (leading) {
|
||||
it = GetOldest(id);
|
||||
}
|
||||
static const timespec too_old = { EXPIRE_HOUR_THRESHOLD * 60 * 60, 0 };
|
||||
static const timespec too_old = {EXPIRE_HOUR_THRESHOLD * 60 * 60, 0};
|
||||
LogBufferElementCollection::iterator lastt;
|
||||
lastt = mLogElements.end();
|
||||
--lastt;
|
||||
|
@ -722,9 +696,8 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
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->getUid();
|
||||
|
||||
if (hasBlacklist && prune_->naughty(element)) {
|
||||
last.clear(element);
|
||||
|
@ -755,10 +728,9 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
|
||||
if (dropped) {
|
||||
last.add(element);
|
||||
if (worstPid &&
|
||||
((!gc && (element->getPid() == worstPid)) ||
|
||||
(mLastWorstPidOfSystem[id].find(element->getPid()) ==
|
||||
mLastWorstPidOfSystem[id].end()))) {
|
||||
if (worstPid && ((!gc && element->getPid() == worstPid) ||
|
||||
mLastWorstPidOfSystem[id].find(element->getPid()) ==
|
||||
mLastWorstPidOfSystem[id].end())) {
|
||||
// element->getUid() 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.
|
||||
|
@ -772,8 +744,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if ((key != worst) ||
|
||||
(worstPid && (element->getPid() != worstPid))) {
|
||||
if (key != worst || (worstPid && element->getPid() != worstPid)) {
|
||||
leading = false;
|
||||
last.clear(element);
|
||||
++it;
|
||||
|
@ -801,16 +772,14 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
it = erase(it, true);
|
||||
} else {
|
||||
last.add(element);
|
||||
if (worstPid &&
|
||||
(!gc || (mLastWorstPidOfSystem[id].find(worstPid) ==
|
||||
mLastWorstPidOfSystem[id].end()))) {
|
||||
if (worstPid && (!gc || mLastWorstPidOfSystem[id].find(worstPid) ==
|
||||
mLastWorstPidOfSystem[id].end())) {
|
||||
// element->getUid() 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;
|
||||
}
|
||||
if ((!gc && !worstPid) ||
|
||||
(mLastWorst[id].find(worst) == mLastWorst[id].end())) {
|
||||
if ((!gc && !worstPid) || mLastWorst[id].find(worst) == mLastWorst[id].end()) {
|
||||
mLastWorst[id][worst] = it;
|
||||
}
|
||||
++it;
|
||||
|
@ -882,7 +851,7 @@ bool LogBuffer::prune(log_id_t id, unsigned long pruneRows, uid_t caller_uid) {
|
|||
}
|
||||
|
||||
// clear all rows of type "id" from the buffer.
|
||||
bool LogBuffer::clear(log_id_t id, uid_t uid) {
|
||||
bool ChattyLogBuffer::Clear(log_id_t id, uid_t uid) {
|
||||
bool busy = true;
|
||||
// If it takes more than 4 tries (seconds) to clear, then kill reader(s)
|
||||
for (int retry = 4;;) {
|
||||
|
@ -903,7 +872,7 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
|
|||
for (const auto& reader_thread : reader_list_->reader_threads()) {
|
||||
if (reader_thread->IsWatching(id)) {
|
||||
android::prdebug(
|
||||
"Kicking blocked reader, pid %d, from LogBuffer::clear()\n",
|
||||
"Kicking blocked reader, pid %d, from ChattyLogBuffer::clear()\n",
|
||||
reader_thread->client()->getPid());
|
||||
reader_thread->release_Locked();
|
||||
}
|
||||
|
@ -922,7 +891,7 @@ bool LogBuffer::clear(log_id_t id, uid_t uid) {
|
|||
}
|
||||
|
||||
// set the total space allocated to "id"
|
||||
int LogBuffer::setSize(log_id_t id, unsigned long size) {
|
||||
int ChattyLogBuffer::SetSize(log_id_t id, unsigned long size) {
|
||||
// Reasonable limits ...
|
||||
if (!__android_logger_valid_buffer_size(size)) {
|
||||
return -1;
|
||||
|
@ -934,14 +903,14 @@ int LogBuffer::setSize(log_id_t id, unsigned long size) {
|
|||
}
|
||||
|
||||
// get the total space allocated to "id"
|
||||
unsigned long LogBuffer::getSize(log_id_t id) {
|
||||
unsigned long ChattyLogBuffer::GetSize(log_id_t id) {
|
||||
rdlock();
|
||||
size_t retval = log_buffer_size(id);
|
||||
unlock();
|
||||
return retval;
|
||||
}
|
||||
|
||||
uint64_t LogBuffer::flushTo(
|
||||
uint64_t ChattyLogBuffer::FlushTo(
|
||||
SocketClient* reader, uint64_t start, pid_t* lastTid, bool privileged, bool security,
|
||||
const std::function<FlushToResult(const LogBufferElement* element)>& filter) {
|
||||
LogBufferElementCollection::iterator it;
|
||||
|
@ -999,7 +968,7 @@ uint64_t LogBuffer::flushTo(
|
|||
// is due to spam filter. chatty to chatty of different
|
||||
// source is also due to spam filter.
|
||||
lastTid[element->getLogId()] =
|
||||
(element->getDropped() && !sameTid) ? 0 : element->getTid();
|
||||
(element->getDropped() && !sameTid) ? 0 : element->getTid();
|
||||
}
|
||||
|
||||
unlock();
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (C) 2012-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.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <android/log.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
#include "LogBuffer.h"
|
||||
#include "LogBufferElement.h"
|
||||
#include "LogStatistics.h"
|
||||
#include "LogTags.h"
|
||||
#include "LogWhiteBlackList.h"
|
||||
|
||||
typedef std::list<LogBufferElement*> LogBufferElementCollection;
|
||||
|
||||
class LogReaderList;
|
||||
class LogReaderThread;
|
||||
|
||||
class ChattyLogBuffer : public LogBuffer {
|
||||
LogBufferElementCollection mLogElements;
|
||||
pthread_rwlock_t mLogElementsLock;
|
||||
|
||||
// watermark of any worst/chatty uid processing
|
||||
typedef std::unordered_map<uid_t, LogBufferElementCollection::iterator> LogBufferIteratorMap;
|
||||
LogBufferIteratorMap mLastWorst[LOG_ID_MAX];
|
||||
// watermark of any worst/chatty pid of system processing
|
||||
typedef std::unordered_map<pid_t, LogBufferElementCollection::iterator> LogBufferPidIteratorMap;
|
||||
LogBufferPidIteratorMap mLastWorstPidOfSystem[LOG_ID_MAX];
|
||||
|
||||
unsigned long mMaxSize[LOG_ID_MAX];
|
||||
|
||||
LogBufferElement* lastLoggedElements[LOG_ID_MAX];
|
||||
LogBufferElement* droppedElements[LOG_ID_MAX];
|
||||
void log(LogBufferElement* elem);
|
||||
|
||||
public:
|
||||
ChattyLogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune,
|
||||
LogStatistics* stats);
|
||||
~ChattyLogBuffer();
|
||||
void Init() override;
|
||||
|
||||
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(
|
||||
SocketClient* writer, uint64_t start, pid_t* lastTid, bool privileged, bool security,
|
||||
const std::function<FlushToResult(const LogBufferElement* element)>& filter) override;
|
||||
|
||||
bool Clear(log_id_t id, uid_t uid = AID_ROOT) override;
|
||||
unsigned long GetSize(log_id_t id) override;
|
||||
int SetSize(log_id_t id, unsigned long size) override;
|
||||
|
||||
private:
|
||||
void wrlock() { pthread_rwlock_wrlock(&mLogElementsLock); }
|
||||
void rdlock() { pthread_rwlock_rdlock(&mLogElementsLock); }
|
||||
void unlock() { pthread_rwlock_unlock(&mLogElementsLock); }
|
||||
|
||||
void maybePrune(log_id_t id);
|
||||
void kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows);
|
||||
|
||||
bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
|
||||
LogBufferElementCollection::iterator erase(LogBufferElementCollection::iterator it,
|
||||
bool coalesce = false);
|
||||
|
||||
// Returns an iterator to the oldest element for a given log type, or mLogElements.end() if
|
||||
// there are no logs for the given log type. Requires mLogElementsLock to be held.
|
||||
LogBufferElementCollection::iterator GetOldest(log_id_t log_id);
|
||||
|
||||
LogReaderList* reader_list_;
|
||||
LogTags* tags_;
|
||||
PruneList* prune_;
|
||||
LogStatistics* stats_;
|
||||
|
||||
// Keeps track of the iterator to the oldest log message of a given log type, as an
|
||||
// optimization when pruning logs. Use GetOldest() to retrieve.
|
||||
std::optional<LogBufferElementCollection::iterator> oldest_[LOG_ID_MAX];
|
||||
};
|
|
@ -81,7 +81,7 @@ int CommandListener::ClearCmd::runCommand(SocketClient* cli, int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
cli->sendMsg(buf()->clear((log_id_t)id, uid) ? "busy" : "success");
|
||||
cli->sendMsg(buf()->Clear((log_id_t)id, uid) ? "busy" : "success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ int CommandListener::GetBufSizeCmd::runCommand(SocketClient* cli, int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
unsigned long size = buf()->getSize((log_id_t)id);
|
||||
unsigned long size = buf()->GetSize((log_id_t)id);
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "%lu", size);
|
||||
cli->sendMsg(buf);
|
||||
|
@ -126,7 +126,7 @@ int CommandListener::SetBufSizeCmd::runCommand(SocketClient* cli, int argc,
|
|||
}
|
||||
|
||||
unsigned long size = atol(argv[2]);
|
||||
if (buf()->setSize((log_id_t)id, size)) {
|
||||
if (buf()->SetSize((log_id_t)id, size)) {
|
||||
cli->sendMsg("Range Error");
|
||||
return 0;
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ int CommandListener::ReinitCmd::runCommand(SocketClient* cli, int /*argc*/,
|
|||
setname();
|
||||
|
||||
android::prdebug("logd reinit");
|
||||
buf()->init();
|
||||
buf()->Init();
|
||||
prune()->init(nullptr);
|
||||
|
||||
// This only works on userdebug and eng devices to re-read the
|
||||
|
|
|
@ -274,9 +274,8 @@ int LogAudit::logPrint(const char* fmt, ...) {
|
|||
memcpy(event->data + str_len - denial_metadata.length(),
|
||||
denial_metadata.c_str(), denial_metadata.length());
|
||||
|
||||
rc = logbuf->log(
|
||||
LOG_ID_EVENTS, now, uid, pid, tid, reinterpret_cast<char*>(event),
|
||||
(message_len <= UINT16_MAX) ? (uint16_t)message_len : UINT16_MAX);
|
||||
rc = logbuf->Log(LOG_ID_EVENTS, now, uid, pid, tid, reinterpret_cast<char*>(event),
|
||||
(message_len <= UINT16_MAX) ? (uint16_t)message_len : UINT16_MAX);
|
||||
if (rc >= 0) {
|
||||
notify |= 1 << LOG_ID_EVENTS;
|
||||
}
|
||||
|
@ -328,9 +327,8 @@ int LogAudit::logPrint(const char* fmt, ...) {
|
|||
strncpy(newstr + 1 + str_len + prefix_len + suffix_len,
|
||||
denial_metadata.c_str(), denial_metadata.length());
|
||||
|
||||
rc = logbuf->log(
|
||||
LOG_ID_MAIN, now, uid, pid, tid, newstr,
|
||||
(message_len <= UINT16_MAX) ? (uint16_t)message_len : UINT16_MAX);
|
||||
rc = logbuf->Log(LOG_ID_MAIN, now, uid, pid, tid, newstr,
|
||||
(message_len <= UINT16_MAX) ? (uint16_t)message_len : UINT16_MAX);
|
||||
|
||||
if (rc >= 0) {
|
||||
notify |= 1 << LOG_ID_MAIN;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2012-2014 The Android Open Source Project
|
||||
* 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.
|
||||
|
@ -18,23 +18,12 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include <android/log.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <log/log.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
#include "LogBufferElement.h"
|
||||
#include "LogStatistics.h"
|
||||
#include "LogTags.h"
|
||||
#include "LogWhiteBlackList.h"
|
||||
|
||||
typedef std::list<LogBufferElement*> LogBufferElementCollection;
|
||||
|
||||
class LogReaderList;
|
||||
class LogReaderThread;
|
||||
|
||||
enum class FlushToResult {
|
||||
kSkip,
|
||||
|
@ -43,71 +32,23 @@ enum class FlushToResult {
|
|||
};
|
||||
|
||||
class LogBuffer {
|
||||
LogBufferElementCollection mLogElements;
|
||||
pthread_rwlock_t mLogElementsLock;
|
||||
|
||||
// watermark of any worst/chatty uid processing
|
||||
typedef std::unordered_map<uid_t, LogBufferElementCollection::iterator>
|
||||
LogBufferIteratorMap;
|
||||
LogBufferIteratorMap mLastWorst[LOG_ID_MAX];
|
||||
// watermark of any worst/chatty pid of system processing
|
||||
typedef std::unordered_map<pid_t, LogBufferElementCollection::iterator>
|
||||
LogBufferPidIteratorMap;
|
||||
LogBufferPidIteratorMap mLastWorstPidOfSystem[LOG_ID_MAX];
|
||||
|
||||
unsigned long mMaxSize[LOG_ID_MAX];
|
||||
|
||||
LogBufferElement* lastLoggedElements[LOG_ID_MAX];
|
||||
LogBufferElement* droppedElements[LOG_ID_MAX];
|
||||
void log(LogBufferElement* elem);
|
||||
|
||||
public:
|
||||
LogBuffer(LogReaderList* reader_list, LogTags* tags, PruneList* prune, LogStatistics* stats);
|
||||
~LogBuffer();
|
||||
void init();
|
||||
virtual ~LogBuffer() {}
|
||||
|
||||
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);
|
||||
virtual void Init() = 0;
|
||||
|
||||
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)
|
||||
uint64_t flushTo(SocketClient* writer, uint64_t start,
|
||||
pid_t* lastTid, // &lastTid[LOG_ID_MAX] or nullptr
|
||||
bool privileged, bool security,
|
||||
const std::function<FlushToResult(const LogBufferElement* element)>& filter);
|
||||
virtual uint64_t FlushTo(
|
||||
SocketClient* writer, uint64_t start,
|
||||
pid_t* last_tid, // nullable
|
||||
bool privileged, bool security,
|
||||
const std::function<FlushToResult(const LogBufferElement* element)>& filter) = 0;
|
||||
|
||||
bool clear(log_id_t id, uid_t uid = AID_ROOT);
|
||||
unsigned long getSize(log_id_t id);
|
||||
int setSize(log_id_t id, unsigned long size);
|
||||
|
||||
private:
|
||||
void wrlock() {
|
||||
pthread_rwlock_wrlock(&mLogElementsLock);
|
||||
}
|
||||
void rdlock() {
|
||||
pthread_rwlock_rdlock(&mLogElementsLock);
|
||||
}
|
||||
void unlock() {
|
||||
pthread_rwlock_unlock(&mLogElementsLock);
|
||||
}
|
||||
|
||||
void maybePrune(log_id_t id);
|
||||
void kickMe(LogReaderThread* me, log_id_t id, unsigned long pruneRows);
|
||||
|
||||
bool prune(log_id_t id, unsigned long pruneRows, uid_t uid = AID_ROOT);
|
||||
LogBufferElementCollection::iterator erase(
|
||||
LogBufferElementCollection::iterator it, bool coalesce = false);
|
||||
|
||||
// Returns an iterator to the oldest element for a given log type, or mLogElements.end() if
|
||||
// there are no logs for the given log type. Requires mLogElementsLock to be held.
|
||||
LogBufferElementCollection::iterator GetOldest(log_id_t log_id);
|
||||
|
||||
LogReaderList* reader_list_;
|
||||
LogTags* tags_;
|
||||
PruneList* prune_;
|
||||
LogStatistics* stats_;
|
||||
|
||||
// Keeps track of the iterator to the oldest log message of a given log type, as an
|
||||
// optimization when pruning logs. Use GetOldest() to retrieve.
|
||||
std::optional<LogBufferElementCollection::iterator> oldest_[LOG_ID_MAX];
|
||||
};
|
||||
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;
|
||||
};
|
|
@ -27,9 +27,9 @@
|
|||
#include <log/log_read.h>
|
||||
#include <private/android_logger.h>
|
||||
|
||||
#include "LogBuffer.h"
|
||||
#include "LogCommand.h"
|
||||
#include "LogReader.h"
|
||||
#include "LogStatistics.h"
|
||||
#include "LogUtils.h"
|
||||
|
||||
const uint64_t LogBufferElement::FLUSH_ERROR(0);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <log/log.h>
|
||||
#include <sysutils/SocketClient.h>
|
||||
|
||||
class LogBuffer;
|
||||
class LogStatistics;
|
||||
|
||||
#define EXPIRE_HOUR_THRESHOLD 24 // Only expire chatty UID logs to preserve
|
||||
|
@ -34,8 +33,6 @@ class LogStatistics;
|
|||
#define EXPIRE_RATELIMIT 10 // maximum rate in seconds to report expiration
|
||||
|
||||
class __attribute__((packed)) LogBufferElement {
|
||||
friend LogBuffer;
|
||||
|
||||
// sized to match reality of incoming log packets
|
||||
const uint32_t mUid;
|
||||
const uint32_t mPid;
|
||||
|
|
|
@ -767,7 +767,7 @@ int LogKlog::log(const char* buf, ssize_t len) {
|
|||
}
|
||||
|
||||
// Log message
|
||||
int rc = logbuf->log(LOG_ID_KERNEL, now, uid, pid, tid, newstr, (uint16_t)n);
|
||||
int rc = logbuf->Log(LOG_ID_KERNEL, now, uid, pid, tid, newstr, (uint16_t)n);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ void LogListener::HandleData() {
|
|||
// NB: hdr.msg_flags & MSG_TRUNC is not tested, silently passing a
|
||||
// truncated message to the logs.
|
||||
|
||||
logbuf_->log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
|
||||
logbuf_->Log(logId, header->realtime, cred->uid, cred->pid, header->tid, msg,
|
||||
((size_t)n <= UINT16_MAX) ? (uint16_t)n : UINT16_MAX);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <chrono>
|
||||
|
||||
#include <cutils/sockets.h>
|
||||
#include <private/android_filesystem_config.h>
|
||||
#include <private/android_logger.h>
|
||||
|
||||
#include "LogBuffer.h"
|
||||
|
@ -158,7 +159,7 @@ bool LogReader::onDataAvailable(SocketClient* cli) {
|
|||
return FlushToResult::kSkip;
|
||||
};
|
||||
|
||||
log_buffer_->flushTo(cli, sequence, nullptr, privileged, can_read_security, log_find_start);
|
||||
log_buffer_->FlushTo(cli, sequence, nullptr, privileged, can_read_security, log_find_start);
|
||||
|
||||
if (!start_time_set) {
|
||||
if (nonBlock) {
|
||||
|
|
|
@ -84,13 +84,13 @@ void LogReaderThread::ThreadFunction() {
|
|||
lock.unlock();
|
||||
|
||||
if (tail_) {
|
||||
logbuf.flushTo(client, start, nullptr, privileged_, can_read_security_logs_,
|
||||
logbuf.FlushTo(client, start, nullptr, privileged_, can_read_security_logs_,
|
||||
std::bind(&LogReaderThread::FilterFirstPass, this, _1));
|
||||
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 = logbuf.flushTo(client, start, last_tid_, privileged_, can_read_security_logs_,
|
||||
start = logbuf.FlushTo(client, start, last_tid_, privileged_, can_read_security_logs_,
|
||||
std::bind(&LogReaderThread::FilterSecondPass, this, _1));
|
||||
|
||||
// We only ignore entries before the original start time for the first flushTo(), if we
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
class LogReader;
|
||||
class LogBufferElement;
|
||||
class LogReaderList;
|
||||
|
||||
class LogReaderThread {
|
||||
public:
|
||||
|
|
|
@ -25,6 +25,7 @@ cc_fuzz {
|
|||
"liblog",
|
||||
"liblogd",
|
||||
"libcutils",
|
||||
"libsysutils",
|
||||
],
|
||||
cflags: ["-Werror"],
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
#include <string>
|
||||
|
||||
#include "../LogBuffer.h"
|
||||
#include "../ChattyLogBuffer.h"
|
||||
#include "../LogReaderList.h"
|
||||
#include "../LogReaderThread.h"
|
||||
#include "../LogStatistics.h"
|
||||
|
@ -72,7 +72,7 @@ int write_log_messages(const uint8_t** pdata, size_t* data_left, LogBuffer* log_
|
|||
|
||||
// Other elements not in enum.
|
||||
log_id_t log_id = static_cast<log_id_t>(unsigned(logInput->log_id) % (LOG_ID_MAX + 1));
|
||||
log_buffer->log(log_id, logInput->realtime, logInput->uid, logInput->pid, logInput->tid, msg,
|
||||
log_buffer->Log(log_id, logInput->realtime, logInput->uid, logInput->pid, logInput->tid, msg,
|
||||
sizeof(uint32_t) + msg_length + 1);
|
||||
stats->Format(logInput->uid, logInput->pid, logInput->log_mask);
|
||||
*pdata = data;
|
||||
|
@ -100,21 +100,21 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||
LogTags tags;
|
||||
PruneList prune_list;
|
||||
LogStatistics stats(true);
|
||||
LogBuffer log_buffer(&reader_list, &tags, &prune_list, &stats);
|
||||
LogBuffer* log_buffer = new ChattyLogBuffer(&reader_list, &tags, &prune_list, &stats);
|
||||
size_t data_left = size;
|
||||
const uint8_t** pdata = &data;
|
||||
|
||||
prune_list.init(nullptr);
|
||||
// We want to get pruning code to get called.
|
||||
log_id_for_each(i) { log_buffer.setSize(i, 10000); }
|
||||
log_id_for_each(i) { log_buffer->SetSize(i, 10000); }
|
||||
|
||||
while (data_left >= sizeof(LogInput) + 2 * sizeof(uint8_t)) {
|
||||
if (!write_log_messages(pdata, &data_left, &log_buffer, &stats)) {
|
||||
if (!write_log_messages(pdata, &data_left, log_buffer, &stats)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
log_id_for_each(i) { log_buffer.clear(i); }
|
||||
log_id_for_each(i) { log_buffer->Clear(i, 0); }
|
||||
return 0;
|
||||
}
|
||||
} // namespace android
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include <processgroup/sched_policy.h>
|
||||
#include <utils/threads.h>
|
||||
|
||||
#include "ChattyLogBuffer.h"
|
||||
#include "CommandListener.h"
|
||||
#include "LogAudit.h"
|
||||
#include "LogBuffer.h"
|
||||
|
@ -288,7 +289,7 @@ int main(int argc, char* argv[]) {
|
|||
|
||||
// LogBuffer is the object which is responsible for holding all
|
||||
// log entries.
|
||||
LogBuffer* logBuf = new LogBuffer(&reader_list, &log_tags, &prune_list, &log_statistics);
|
||||
LogBuffer* logBuf = new ChattyLogBuffer(&reader_list, &log_tags, &prune_list, &log_statistics);
|
||||
|
||||
// LogReader listens on /dev/socket/logdr. When a client
|
||||
// connects, log entries in the LogBuffer are written to the client.
|
||||
|
|
Loading…
Reference in New Issue