logd: liblog: logcat: Add LogWhiteBlackList
- liblog android_logger_get_log_size and android_logger_get_readable_size adjusted to return long instead of int because of -G flag extending range NB: ifdef'd only for userdebug and eng builds - liblog Add android_logger_[sg]et_prune_list and android_logger_set_log_size - logcat Add -P, -p and -G flags - logd Add LogWhiteBlackList and configurable log size Change-Id: I1572338c1b34bd968ad7867857ef708156ec3b6a
This commit is contained in:
parent
3c4919e474
commit
18a5432158
15 changed files with 832 additions and 68 deletions
|
@ -140,14 +140,23 @@ struct logger;
|
|||
log_id_t android_logger_get_id(struct logger *logger);
|
||||
|
||||
int android_logger_clear(struct logger *logger);
|
||||
int android_logger_get_log_size(struct logger *logger);
|
||||
int android_logger_get_log_readable_size(struct logger *logger);
|
||||
long android_logger_get_log_size(struct logger *logger);
|
||||
#ifdef USERDEBUG_BUILD
|
||||
int android_logger_set_log_size(struct logger *logger, unsigned long size);
|
||||
#endif
|
||||
long android_logger_get_log_readable_size(struct logger *logger);
|
||||
int android_logger_get_log_version(struct logger *logger);
|
||||
|
||||
struct logger_list;
|
||||
|
||||
ssize_t android_logger_get_statistics(struct logger_list *logger_list,
|
||||
char *buf, size_t len);
|
||||
#ifdef USERDEBUG_BUILD
|
||||
ssize_t android_logger_get_prune_list(struct logger_list *logger_list,
|
||||
char *buf, size_t len);
|
||||
int android_logger_set_prune_list(struct logger_list *logger_list,
|
||||
char *buf, size_t len);
|
||||
#endif
|
||||
|
||||
struct logger_list *android_logger_list_alloc(int mode,
|
||||
unsigned int tail,
|
||||
|
|
|
@ -22,6 +22,10 @@ else
|
|||
liblog_sources := logd_write_kern.c
|
||||
endif
|
||||
|
||||
ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
|
||||
liblog_cflags := -DUSERDEBUG_BUILD=1
|
||||
endif
|
||||
|
||||
# some files must not be compiled when building against Mingw
|
||||
# they correspond to features not used by our host development tools
|
||||
# which are also hard or even impossible to port to native Win32
|
||||
|
@ -80,11 +84,13 @@ include $(BUILD_HOST_STATIC_LIBRARY)
|
|||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := liblog
|
||||
LOCAL_SRC_FILES := $(liblog_target_sources)
|
||||
LOCAL_CFLAGS := $(liblog_cflags)
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := liblog
|
||||
LOCAL_WHOLE_STATIC_LIBRARIES := liblog
|
||||
LOCAL_CFLAGS := $(liblog_cflags)
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
include $(call first-makefiles-under,$(LOCAL_PATH))
|
||||
|
|
|
@ -296,11 +296,8 @@ done:
|
|||
return ret;
|
||||
}
|
||||
|
||||
int android_logger_clear(struct logger *logger)
|
||||
static int check_log_success(char *buf, ssize_t ret)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
ssize_t ret = send_log_msg(logger, "clear %d", buf, sizeof(buf));
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -312,8 +309,16 @@ int android_logger_clear(struct logger *logger)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int android_logger_clear(struct logger *logger)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
return check_log_success(buf,
|
||||
send_log_msg(logger, "clear %d", buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
/* returns the total size of the log's ring buffer */
|
||||
int android_logger_get_log_size(struct logger *logger)
|
||||
long android_logger_get_log_size(struct logger *logger)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
|
@ -326,14 +331,28 @@ int android_logger_get_log_size(struct logger *logger)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return atoi(buf);
|
||||
return atol(buf);
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
int android_logger_set_log_size(struct logger *logger, unsigned long size)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
snprintf(buf, sizeof(buf), "setLogSize %d %lu",
|
||||
logger ? logger->id : (unsigned) -1, size);
|
||||
|
||||
return check_log_success(buf, send_log_msg(NULL, NULL, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
#endif /* USERDEBUG_BUILD */
|
||||
|
||||
/*
|
||||
* returns the readable size of the log's ring buffer (that is, amount of the
|
||||
* log consumed)
|
||||
*/
|
||||
int android_logger_get_log_readable_size(struct logger *logger)
|
||||
long android_logger_get_log_readable_size(struct logger *logger)
|
||||
{
|
||||
char buf[512];
|
||||
|
||||
|
@ -346,7 +365,7 @@ int android_logger_get_log_readable_size(struct logger *logger)
|
|||
return -1;
|
||||
}
|
||||
|
||||
return atoi(buf);
|
||||
return atol(buf);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -383,6 +402,32 @@ ssize_t android_logger_get_statistics(struct logger_list *logger_list,
|
|||
return send_log_msg(NULL, NULL, buf, len);
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return send_log_msg(NULL, "getPruneList", buf, len);
|
||||
}
|
||||
|
||||
int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
const char cmd[] = "setPruneList ";
|
||||
const size_t cmdlen = sizeof(cmd) - 1;
|
||||
|
||||
if (strlen(buf) > (len - cmdlen)) {
|
||||
return -ENOMEM; /* KISS */
|
||||
}
|
||||
memmove(buf + cmdlen, buf, len - cmdlen);
|
||||
buf[len - 1] = '\0';
|
||||
memcpy(buf, cmd, cmdlen);
|
||||
|
||||
return check_log_success(buf, send_log_msg(NULL, NULL, buf, len));
|
||||
}
|
||||
|
||||
#endif /* USERDEBUG_BUILD */
|
||||
|
||||
struct logger_list *android_logger_list_alloc(int mode,
|
||||
unsigned int tail,
|
||||
pid_t pid)
|
||||
|
|
|
@ -227,16 +227,26 @@ int android_logger_clear(struct logger *logger)
|
|||
}
|
||||
|
||||
/* returns the total size of the log's ring buffer */
|
||||
int android_logger_get_log_size(struct logger *logger)
|
||||
long android_logger_get_log_size(struct logger *logger)
|
||||
{
|
||||
return logger_ioctl(logger, LOGGER_GET_LOG_BUF_SIZE, O_RDWR);
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
int android_logger_set_log_size(struct logger *logger UNUSED,
|
||||
unsigned long size UNUSED)
|
||||
{
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#endif /* USERDEBUG_BUILD */
|
||||
|
||||
/*
|
||||
* returns the readable size of the log's ring buffer (that is, amount of the
|
||||
* log consumed)
|
||||
*/
|
||||
int android_logger_get_log_readable_size(struct logger *logger)
|
||||
long android_logger_get_log_readable_size(struct logger *logger)
|
||||
{
|
||||
return logger_ioctl(logger, LOGGER_GET_LOG_LEN, O_RDONLY);
|
||||
}
|
||||
|
@ -253,15 +263,34 @@ int android_logger_get_log_version(struct logger *logger)
|
|||
/*
|
||||
* returns statistics
|
||||
*/
|
||||
static const char unsupported[] = "18\nNot Supported\n\f";
|
||||
|
||||
ssize_t android_logger_get_statistics(struct logger_list *logger_list UNUSED,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
static const char unsupported[] = "18\nNot Supported\n\f";
|
||||
strncpy(buf, unsupported, len);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
ssize_t android_logger_get_prune_list(struct logger_list *logger_list UNUSED,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
strncpy(buf, unsupported, len);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
int android_logger_set_prune_list(struct logger_list *logger_list UNUSED,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
static const char unsupported_error[] = "Unsupported";
|
||||
strncpy(buf, unsupported, len);
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
#endif /* USERDEBUG_BUILD */
|
||||
|
||||
struct logger_list *android_logger_list_alloc(int mode,
|
||||
unsigned int tail,
|
||||
pid_t pid)
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
|
||||
LOCAL_CFLAGS += -DUSERDEBUG_BUILD=1
|
||||
endif
|
||||
|
||||
LOCAL_SRC_FILES:= logcat.cpp event.logtags
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := liblog
|
||||
|
|
|
@ -229,8 +229,19 @@ static void show_help(const char *cmd)
|
|||
" 'events' or 'all'. Multiple -b parameters are allowed and\n"
|
||||
" results are interleaved. The default is -b main -b system.\n"
|
||||
" -B output the log in binary.\n"
|
||||
" -S output statistics");
|
||||
" -S output statistics.\n");
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
fprintf(stderr, "--------------------- eng & userdebug builds only ---------------------------\n"
|
||||
" -G <count> set size of log's ring buffer and exit\n"
|
||||
" -p output prune white and ~black list\n"
|
||||
" -P '<list> ...' set prune white and ~black list; UID, /PID or !(worst UID)\n"
|
||||
" default is ~!, prune worst UID.\n"
|
||||
"-----------------------------------------------------------------------------\n"
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
fprintf(stderr,"\nfilterspecs are a series of \n"
|
||||
" <tag>[:priority]\n\n"
|
||||
|
@ -279,6 +290,11 @@ int main(int argc, char **argv)
|
|||
int hasSetLogFormat = 0;
|
||||
int clearLog = 0;
|
||||
int getLogSize = 0;
|
||||
#ifdef USERDEBUG_BUILD
|
||||
unsigned long setLogSize = 0;
|
||||
int getPruneList = 0;
|
||||
char *setPruneList = NULL;
|
||||
#endif
|
||||
int printStatistics = 0;
|
||||
int mode = O_RDONLY;
|
||||
const char *forceFilters = NULL;
|
||||
|
@ -305,7 +321,13 @@ int main(int argc, char **argv)
|
|||
for (;;) {
|
||||
int ret;
|
||||
|
||||
ret = getopt(argc, argv, "cdt:T:gsQf:r::n:v:b:BS");
|
||||
ret = getopt(argc, argv,
|
||||
#ifdef USERDEBUG_BUILD
|
||||
"cdt:T:gG:sQf:r::n:v:b:BSpP:"
|
||||
#else
|
||||
"cdt:T:gsQf:r::n:v:b:BS"
|
||||
#endif
|
||||
);
|
||||
|
||||
if (ret < 0) {
|
||||
break;
|
||||
|
@ -337,6 +359,55 @@ int main(int argc, char **argv)
|
|||
getLogSize = 1;
|
||||
break;
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
case 'G': {
|
||||
// would use atol if not for the multiplier
|
||||
char *cp = optarg;
|
||||
setLogSize = 0;
|
||||
while (('0' <= *cp) && (*cp <= '9')) {
|
||||
setLogSize *= 10;
|
||||
setLogSize += *cp - '0';
|
||||
++cp;
|
||||
}
|
||||
|
||||
switch(*cp) {
|
||||
case 'g':
|
||||
case 'G':
|
||||
setLogSize *= 1024;
|
||||
/* FALLTHRU */
|
||||
case 'm':
|
||||
case 'M':
|
||||
setLogSize *= 1024;
|
||||
/* FALLTHRU */
|
||||
case 'k':
|
||||
case 'K':
|
||||
setLogSize *= 1024;
|
||||
/* FALLTHRU */
|
||||
case '\0':
|
||||
break;
|
||||
|
||||
default:
|
||||
setLogSize = 0;
|
||||
}
|
||||
|
||||
if (!setLogSize) {
|
||||
fprintf(stderr, "ERROR: -G <num><multiplier>\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
getPruneList = 1;
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
setPruneList = optarg;
|
||||
break;
|
||||
|
||||
#endif
|
||||
|
||||
case 'b': {
|
||||
if (strcmp(optarg, "all") == 0) {
|
||||
while (devices) {
|
||||
|
@ -602,8 +673,17 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
if (setLogSize && android_logger_set_log_size(dev->logger, setLogSize)) {
|
||||
perror("setLogSize");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (getLogSize) {
|
||||
int size, readable;
|
||||
long size, readable;
|
||||
|
||||
size = android_logger_get_log_size(dev->logger);
|
||||
if (size < 0) {
|
||||
|
@ -617,7 +697,7 @@ int main(int argc, char **argv)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
printf("%s: ring buffer is %dKb (%dKb consumed), "
|
||||
printf("%s: ring buffer is %ldKb (%ldKb consumed), "
|
||||
"max entry is %db, max payload is %db\n", dev->device,
|
||||
size / 1024, readable / 1024,
|
||||
(int) LOGGER_ENTRY_MAX_LEN, (int) LOGGER_ENTRY_MAX_PAYLOAD);
|
||||
|
@ -626,15 +706,46 @@ int main(int argc, char **argv)
|
|||
dev = dev->next;
|
||||
}
|
||||
|
||||
if (printStatistics) {
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
if (setPruneList) {
|
||||
size_t len = strlen(setPruneList) + 32; // margin to allow rc
|
||||
char *buf = (char *) malloc(len);
|
||||
|
||||
strcpy(buf, setPruneList);
|
||||
int ret = android_logger_set_prune_list(logger_list, buf, len);
|
||||
free(buf);
|
||||
|
||||
if (ret) {
|
||||
perror("setPruneList");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if (
|
||||
#ifdef USERDEBUG_BUILD
|
||||
printStatistics || getPruneList
|
||||
#else
|
||||
printStatistics
|
||||
#endif
|
||||
) {
|
||||
size_t len = 8192;
|
||||
char *buf;
|
||||
|
||||
for(int retry = 32;
|
||||
(retry >= 0) && ((buf = new char [len]));
|
||||
delete [] buf, --retry) {
|
||||
#ifdef USERDEBUG_BUILD
|
||||
if (getPruneList) {
|
||||
android_logger_get_prune_list(logger_list, buf, len);
|
||||
} else {
|
||||
android_logger_get_statistics(logger_list, buf, len);
|
||||
}
|
||||
#else
|
||||
android_logger_get_statistics(logger_list, buf, len);
|
||||
|
||||
#endif
|
||||
buf[len-1] = '\0';
|
||||
size_t ret = atol(buf) + 1;
|
||||
if (ret < 4) {
|
||||
|
@ -650,7 +761,7 @@ int main(int argc, char **argv)
|
|||
}
|
||||
|
||||
if (!buf) {
|
||||
perror("statistics read");
|
||||
perror("response read");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
@ -679,6 +790,11 @@ int main(int argc, char **argv)
|
|||
if (getLogSize) {
|
||||
exit(0);
|
||||
}
|
||||
#ifdef USERDEBUG_BUILD
|
||||
if (setLogSize || setPruneList) {
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
if (clearLog) {
|
||||
exit(0);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ include $(CLEAR_VARS)
|
|||
|
||||
LOCAL_MODULE:= logd
|
||||
|
||||
ifneq ($(filter userdebug eng,$(TARGET_BUILD_VARIANT)),)
|
||||
LOCAL_CFLAGS += -DUSERDEBUG_BUILD=1
|
||||
endif
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
main.cpp \
|
||||
LogCommand.cpp \
|
||||
|
@ -14,7 +18,8 @@ LOCAL_SRC_FILES := \
|
|||
LogBuffer.cpp \
|
||||
LogBufferElement.cpp \
|
||||
LogTimes.cpp \
|
||||
LogStatistics.cpp
|
||||
LogStatistics.cpp \
|
||||
LogWhiteBlackList.cpp
|
||||
|
||||
LOCAL_SHARED_LIBRARIES := \
|
||||
libsysutils \
|
||||
|
|
|
@ -37,8 +37,15 @@ CommandListener::CommandListener(LogBuffer *buf, LogReader * /*reader*/,
|
|||
// registerCmd(new ShutdownCmd(buf, writer, swl));
|
||||
registerCmd(new ClearCmd(buf));
|
||||
registerCmd(new GetBufSizeCmd(buf));
|
||||
#ifdef USERDEBUG_BUILD
|
||||
registerCmd(new SetBufSizeCmd(buf));
|
||||
#endif
|
||||
registerCmd(new GetBufSizeUsedCmd(buf));
|
||||
registerCmd(new GetStatisticsCmd(buf));
|
||||
#ifdef USERDEBUG_BUILD
|
||||
registerCmd(new SetPruneListCmd(buf));
|
||||
registerCmd(new GetPruneListCmd(buf));
|
||||
#endif
|
||||
}
|
||||
|
||||
CommandListener::ShutdownCmd::ShutdownCmd(LogBuffer *buf, LogReader *reader,
|
||||
|
@ -110,6 +117,43 @@ int CommandListener::GetBufSizeCmd::runCommand(SocketClient *cli,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
CommandListener::SetBufSizeCmd::SetBufSizeCmd(LogBuffer *buf)
|
||||
: LogCommand("setLogSize")
|
||||
, mBuf(*buf)
|
||||
{ }
|
||||
|
||||
int CommandListener::SetBufSizeCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
if (!clientHasLogCredentials(cli)) {
|
||||
cli->sendMsg("Permission Denied");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc < 3) {
|
||||
cli->sendMsg("Missing Argument");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int id = atoi(argv[1]);
|
||||
if ((id < LOG_ID_MIN) || (LOG_ID_MAX <= id)) {
|
||||
cli->sendMsg("Range Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long size = atol(argv[2]);
|
||||
if (mBuf.setSize((log_id_t) id, size)) {
|
||||
cli->sendMsg("Range Error");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cli->sendMsg("success");
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USERDEBUG_BUILD
|
||||
|
||||
CommandListener::GetBufSizeUsedCmd::GetBufSizeUsedCmd(LogBuffer *buf)
|
||||
: LogCommand("getLogSizeUsed")
|
||||
, mBuf(*buf)
|
||||
|
@ -140,6 +184,24 @@ CommandListener::GetStatisticsCmd::GetStatisticsCmd(LogBuffer *buf)
|
|||
, mBuf(*buf)
|
||||
{ }
|
||||
|
||||
static void package_string(char **strp) {
|
||||
const char *a = *strp;
|
||||
if (!a) {
|
||||
a = "";
|
||||
}
|
||||
|
||||
// Calculate total buffer size prefix, count is the string length w/o nul
|
||||
char fmt[32];
|
||||
for(size_t l = strlen(a), y = 0, x = 6; y != x; y = x, x = strlen(fmt) - 2) {
|
||||
snprintf(fmt, sizeof(fmt), "%zu\n%%s\n\f", l + x);
|
||||
}
|
||||
|
||||
char *b = *strp;
|
||||
*strp = NULL;
|
||||
asprintf(strp, fmt, a);
|
||||
free(b);
|
||||
}
|
||||
|
||||
int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
uid_t uid = cli->getUid();
|
||||
|
@ -167,8 +229,69 @@ int CommandListener::GetStatisticsCmd::runCommand(SocketClient *cli,
|
|||
if (!buf) {
|
||||
cli->sendMsg("Failed");
|
||||
} else {
|
||||
package_string(&buf);
|
||||
cli->sendMsg(buf);
|
||||
free(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
CommandListener::GetPruneListCmd::GetPruneListCmd(LogBuffer *buf)
|
||||
: LogCommand("getPruneList")
|
||||
, mBuf(*buf)
|
||||
{ }
|
||||
|
||||
int CommandListener::GetPruneListCmd::runCommand(SocketClient *cli,
|
||||
int /*argc*/, char ** /*argv*/) {
|
||||
char *buf = NULL;
|
||||
mBuf.formatPrune(&buf);
|
||||
if (!buf) {
|
||||
cli->sendMsg("Failed");
|
||||
} else {
|
||||
package_string(&buf);
|
||||
cli->sendMsg(buf);
|
||||
free(buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
CommandListener::SetPruneListCmd::SetPruneListCmd(LogBuffer *buf)
|
||||
: LogCommand("setPruneList")
|
||||
, mBuf(*buf)
|
||||
{ }
|
||||
|
||||
int CommandListener::SetPruneListCmd::runCommand(SocketClient *cli,
|
||||
int argc, char **argv) {
|
||||
if (!clientHasLogCredentials(cli)) {
|
||||
cli->sendMsg("Permission Denied");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *cp = NULL;
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
char *p = cp;
|
||||
if (p) {
|
||||
cp = NULL;
|
||||
asprintf(&cp, "%s %s", p, argv[i]);
|
||||
free(p);
|
||||
} else {
|
||||
asprintf(&cp, "%s", argv[i]);
|
||||
}
|
||||
}
|
||||
|
||||
int ret = mBuf.initPrune(cp);
|
||||
free(cp);
|
||||
|
||||
if (ret) {
|
||||
cli->sendMsg("Invalid");
|
||||
return 0;
|
||||
}
|
||||
|
||||
cli->sendMsg("success");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // USERDEBUG_BUILD
|
||||
|
|
|
@ -53,8 +53,15 @@ private:
|
|||
|
||||
LogBufferCmd(Clear)
|
||||
LogBufferCmd(GetBufSize)
|
||||
#ifdef USERDEBUG_BUILD
|
||||
LogBufferCmd(SetBufSize)
|
||||
#endif
|
||||
LogBufferCmd(GetBufSizeUsed)
|
||||
LogBufferCmd(GetStatistics)
|
||||
#ifdef USERDEBUG_BUILD
|
||||
LogBufferCmd(GetPruneList)
|
||||
LogBufferCmd(SetPruneList)
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,13 +23,25 @@
|
|||
|
||||
#include "LogBuffer.h"
|
||||
#include "LogStatistics.h"
|
||||
#include "LogWhiteBlackList.h"
|
||||
#include "LogReader.h"
|
||||
|
||||
// Default
|
||||
#define LOG_BUFFER_SIZE (256 * 1024) // Tuned on a per-platform basis here?
|
||||
#ifdef USERDEBUG_BUILD
|
||||
#define log_buffer_size(id) mMaxSize[id]
|
||||
#else
|
||||
#define log_buffer_size(id) LOG_BUFFER_SIZE
|
||||
#endif
|
||||
|
||||
LogBuffer::LogBuffer(LastLogTimes *times)
|
||||
: mTimes(*times) {
|
||||
pthread_mutex_init(&mLogElementsLock, NULL);
|
||||
#ifdef USERDEBUG_BUILD
|
||||
log_id_for_each(i) {
|
||||
mMaxSize[i] = LOG_BUFFER_SIZE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void LogBuffer::log(log_id_t log_id, log_time realtime,
|
||||
|
@ -100,8 +112,8 @@ void LogBuffer::log(log_id_t log_id, log_time realtime,
|
|||
// mLogElementsLock must be held when this function is called.
|
||||
void LogBuffer::maybePrune(log_id_t id) {
|
||||
size_t sizes = stats.sizes(id);
|
||||
if (sizes > LOG_BUFFER_SIZE) {
|
||||
size_t sizeOver90Percent = sizes - ((LOG_BUFFER_SIZE * 9) / 10);
|
||||
if (sizes > log_buffer_size(id)) {
|
||||
size_t sizeOver90Percent = sizes - ((log_buffer_size(id) * 9) / 10);
|
||||
size_t elements = stats.elements(id);
|
||||
unsigned long pruneRows = elements * sizeOver90Percent / sizes;
|
||||
elements /= 10;
|
||||
|
@ -140,18 +152,23 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows) {
|
|||
size_t worst_sizes = 0;
|
||||
size_t second_worst_sizes = 0;
|
||||
|
||||
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;
|
||||
#ifdef USERDEBUG_BUILD
|
||||
if (mPrune.worstUidEnabled())
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +180,14 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows) {
|
|||
break;
|
||||
}
|
||||
|
||||
if ((e->getLogId() == id) && (e->getUid() == worst)) {
|
||||
if (e->getLogId() != id) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
|
||||
uid_t uid = e->getUid();
|
||||
|
||||
if (uid == worst) {
|
||||
it = mLogElements.erase(it);
|
||||
unsigned short len = e->getMsgLen();
|
||||
stats.subtract(len, id, worst, e->getPid());
|
||||
|
@ -174,29 +198,60 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows) {
|
|||
break;
|
||||
}
|
||||
worst_sizes -= len;
|
||||
} else {
|
||||
}
|
||||
#ifdef USERDEBUG_BUILD
|
||||
else if (mPrune.naughty(e)) { // BlackListed
|
||||
it = mLogElements.erase(it);
|
||||
stats.subtract(e->getMsgLen(), id, uid, e->getPid());
|
||||
delete e;
|
||||
pruneRows--;
|
||||
if (pruneRows == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
if (!kick) {
|
||||
if (!kick
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|| !mPrune.worstUidEnabled()
|
||||
#endif
|
||||
) {
|
||||
break; // the following loop will ask bad clients to skip/drop
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
bool whitelist = false;
|
||||
#endif
|
||||
it = mLogElements.begin();
|
||||
while((pruneRows > 0) && (it != mLogElements.end())) {
|
||||
LogBufferElement *e = *it;
|
||||
if (e->getLogId() == id) {
|
||||
if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
|
||||
if (stats.sizes(id) > (2 * LOG_BUFFER_SIZE)) {
|
||||
// kick a misbehaving log reader client off the island
|
||||
oldest->release_Locked();
|
||||
} else {
|
||||
oldest->triggerSkip_Locked(pruneRows);
|
||||
#ifdef USERDEBUG_BUILD
|
||||
if (!whitelist)
|
||||
#endif
|
||||
{
|
||||
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
|
||||
// kick a misbehaving log reader client off the island
|
||||
oldest->release_Locked();
|
||||
} else {
|
||||
oldest->triggerSkip_Locked(pruneRows);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
#ifdef USERDEBUG_BUILD
|
||||
if (mPrune.nice(e)) { // WhiteListed
|
||||
whitelist = true;
|
||||
it++;
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
it = mLogElements.erase(it);
|
||||
stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
|
||||
delete e;
|
||||
|
@ -206,6 +261,32 @@ void LogBuffer::prune(log_id_t id, unsigned long pruneRows) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
if (whitelist && (pruneRows > 0)) {
|
||||
it = mLogElements.begin();
|
||||
while((it != mLogElements.end()) && (pruneRows > 0)) {
|
||||
LogBufferElement *e = *it;
|
||||
if (e->getLogId() == id) {
|
||||
if (oldest && (oldest->mStart <= e->getMonotonicTime())) {
|
||||
if (stats.sizes(id) > (2 * log_buffer_size(id))) {
|
||||
// kick a misbehaving log reader client off the island
|
||||
oldest->release_Locked();
|
||||
} else {
|
||||
oldest->triggerSkip_Locked(pruneRows);
|
||||
}
|
||||
break;
|
||||
}
|
||||
it = mLogElements.erase(it);
|
||||
stats.subtract(e->getMsgLen(), id, e->getUid(), e->getPid());
|
||||
delete e;
|
||||
pruneRows--;
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LogTimeEntry::unlock();
|
||||
}
|
||||
|
||||
|
@ -224,11 +305,37 @@ unsigned long LogBuffer::getSizeUsed(log_id_t id) {
|
|||
return retval;
|
||||
}
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
// set the total space allocated to "id"
|
||||
int LogBuffer::setSize(log_id_t id, unsigned long size) {
|
||||
// Reasonable limits ...
|
||||
if ((size < (64 * 1024)) || ((256 * 1024 * 1024) < size)) {
|
||||
return -1;
|
||||
}
|
||||
pthread_mutex_lock(&mLogElementsLock);
|
||||
log_buffer_size(id) = size;
|
||||
pthread_mutex_unlock(&mLogElementsLock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get the total space allocated to "id"
|
||||
unsigned long LogBuffer::getSize(log_id_t id) {
|
||||
pthread_mutex_lock(&mLogElementsLock);
|
||||
size_t retval = log_buffer_size(id);
|
||||
pthread_mutex_unlock(&mLogElementsLock);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#else // ! USERDEBUG_BUILD
|
||||
|
||||
// get the total space allocated to "id"
|
||||
unsigned long LogBuffer::getSize(log_id_t /*id*/) {
|
||||
return LOG_BUFFER_SIZE;
|
||||
return log_buffer_size(id);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
log_time LogBuffer::flushTo(
|
||||
SocketClient *reader, const log_time start, bool privileged,
|
||||
bool (*filter)(const LogBufferElement *element, void *arg), void *arg) {
|
||||
|
@ -269,7 +376,7 @@ log_time LogBuffer::flushTo(
|
|||
return max;
|
||||
}
|
||||
|
||||
size_t LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
|
||||
void LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask) {
|
||||
log_time oldest(CLOCK_MONOTONIC);
|
||||
|
||||
pthread_mutex_lock(&mLogElementsLock);
|
||||
|
@ -285,9 +392,7 @@ size_t LogBuffer::formatStatistics(char **strp, uid_t uid, unsigned int logMask)
|
|||
}
|
||||
}
|
||||
|
||||
size_t ret = stats.format(strp, uid, logMask, oldest);
|
||||
stats.format(strp, uid, logMask, oldest);
|
||||
|
||||
pthread_mutex_unlock(&mLogElementsLock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "LogBufferElement.h"
|
||||
#include "LogTimes.h"
|
||||
#include "LogStatistics.h"
|
||||
#include "LogWhiteBlackList.h"
|
||||
|
||||
typedef android::List<LogBufferElement *> LogBufferElementCollection;
|
||||
|
||||
|
@ -35,6 +36,12 @@ class LogBuffer {
|
|||
|
||||
LogStatistics stats;
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
PruneList mPrune;
|
||||
|
||||
unsigned long mMaxSize[LOG_ID_MAX];
|
||||
#endif
|
||||
|
||||
public:
|
||||
LastLogTimes &mTimes;
|
||||
|
||||
|
@ -49,9 +56,18 @@ public:
|
|||
|
||||
void clear(log_id_t id);
|
||||
unsigned long getSize(log_id_t id);
|
||||
#ifdef USERDEBUG_BUILD
|
||||
int setSize(log_id_t id, unsigned long size);
|
||||
#endif
|
||||
unsigned long getSizeUsed(log_id_t id);
|
||||
// *strp uses malloc, use free to release.
|
||||
size_t formatStatistics(char **strp, uid_t uid, unsigned int logMask);
|
||||
void formatStatistics(char **strp, uid_t uid, unsigned int logMask);
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
int initPrune(char *cp) { return mPrune.init(cp); }
|
||||
// *strp uses malloc, use free to release.
|
||||
void formatPrune(char **strp) { mPrune.format(strp); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
void maybePrune(log_id_t id);
|
||||
|
|
|
@ -335,8 +335,8 @@ size_t LogStatistics::elementsTotal(log_id_t log_id, uid_t uid, pid_t pid) {
|
|||
return elements;
|
||||
}
|
||||
|
||||
size_t LogStatistics::format(char **buf,
|
||||
uid_t uid, unsigned int logMask, log_time oldest) {
|
||||
void LogStatistics::format(char **buf,
|
||||
uid_t uid, unsigned int logMask, log_time oldest) {
|
||||
const unsigned short spaces_current = 13;
|
||||
const unsigned short spaces_total = 19;
|
||||
|
||||
|
@ -551,20 +551,5 @@ size_t LogStatistics::format(char **buf,
|
|||
}
|
||||
}
|
||||
|
||||
// Calculate total buffer size prefix
|
||||
char re_fmt[32];
|
||||
size_t ret;
|
||||
for(size_t l = string.length(), y = 0, x = 6;
|
||||
y != x;
|
||||
y = x, x = strlen(re_fmt) - 2) {
|
||||
snprintf(re_fmt, sizeof(re_fmt), "%zu\n%%s\n\f", l + x);
|
||||
ret = l + x;
|
||||
}
|
||||
|
||||
android::String8 intermediate = string.format(re_fmt, string.string());
|
||||
string.clear();
|
||||
|
||||
*buf = strdup(intermediate.string());
|
||||
|
||||
return ret;
|
||||
*buf = strdup(string.string());
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ public:
|
|||
pid_t pid = pid_all);
|
||||
|
||||
// *strp = malloc, balance with free
|
||||
size_t format(char **strp, uid_t uid, unsigned int logMask, log_time oldest);
|
||||
void format(char **strp, uid_t uid, unsigned int logMask, log_time oldest);
|
||||
};
|
||||
|
||||
#endif // _LOGD_LOG_STATISTICS_H__
|
||||
|
|
243
logd/LogWhiteBlackList.cpp
Normal file
243
logd/LogWhiteBlackList.cpp
Normal file
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef USERDEBUG_BUILD
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include <utils/String8.h>
|
||||
|
||||
#include "LogWhiteBlackList.h"
|
||||
|
||||
// White and Black list
|
||||
|
||||
Prune::Prune(uid_t uid, pid_t pid)
|
||||
: mUid(uid)
|
||||
, mPid(pid)
|
||||
{ }
|
||||
|
||||
int Prune::cmp(uid_t uid, pid_t pid) const {
|
||||
if ((mUid == uid_all) || (mUid == uid)) {
|
||||
if (mPid == pid_all) {
|
||||
return 0;
|
||||
}
|
||||
return pid - mPid;
|
||||
}
|
||||
return uid - mUid;
|
||||
}
|
||||
|
||||
void Prune::format(char **strp) {
|
||||
if (mUid != uid_all) {
|
||||
asprintf(strp, (mPid != pid_all) ? "%u/%u" : "%u", mUid, mPid);
|
||||
} else {
|
||||
// NB: mPid == pid_all can not happen if mUid == uid_all
|
||||
asprintf(strp, (mPid != pid_all) ? "/%u" : "/", mPid);
|
||||
}
|
||||
}
|
||||
|
||||
PruneList::PruneList()
|
||||
: mWorstUidEnabled(true) {
|
||||
mNaughty.clear();
|
||||
mNice.clear();
|
||||
}
|
||||
|
||||
PruneList::~PruneList() {
|
||||
PruneCollection::iterator it;
|
||||
for (it = mNice.begin(); it != mNice.end();) {
|
||||
delete (*it);
|
||||
it = mNice.erase(it);
|
||||
}
|
||||
for (it = mNaughty.begin(); it != mNaughty.end();) {
|
||||
delete (*it);
|
||||
it = mNaughty.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
int PruneList::init(char *str) {
|
||||
mWorstUidEnabled = true;
|
||||
PruneCollection::iterator it;
|
||||
for (it = mNice.begin(); it != mNice.end();) {
|
||||
delete (*it);
|
||||
it = mNice.erase(it);
|
||||
}
|
||||
for (it = mNaughty.begin(); it != mNaughty.end();) {
|
||||
delete (*it);
|
||||
it = mNaughty.erase(it);
|
||||
}
|
||||
|
||||
if (!str) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
mWorstUidEnabled = false;
|
||||
|
||||
for(; *str; ++str) {
|
||||
if (isspace(*str)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PruneCollection *list;
|
||||
if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
|
||||
++str;
|
||||
// special case, translates to worst UID at priority in blacklist
|
||||
if (*str == '!') {
|
||||
mWorstUidEnabled = true;
|
||||
++str;
|
||||
if (!*str) {
|
||||
break;
|
||||
}
|
||||
if (!isspace(*str)) {
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!*str) {
|
||||
return 1;
|
||||
}
|
||||
list = &mNaughty;
|
||||
} else {
|
||||
list = &mNice;
|
||||
}
|
||||
|
||||
uid_t uid = Prune::uid_all;
|
||||
if (isdigit(*str)) {
|
||||
uid = 0;
|
||||
do {
|
||||
uid = uid * 10 + *str++ - '0';
|
||||
} while (isdigit(*str));
|
||||
}
|
||||
|
||||
pid_t pid = Prune::pid_all;
|
||||
if (*str == '/') {
|
||||
++str;
|
||||
if (isdigit(*str)) {
|
||||
pid = 0;
|
||||
do {
|
||||
pid = pid * 10 + *str++ - '0';
|
||||
} while (isdigit(*str));
|
||||
}
|
||||
}
|
||||
|
||||
if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (*str && !isspace(*str)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// insert sequentially into list
|
||||
PruneCollection::iterator it = list->begin();
|
||||
while (it != list->end()) {
|
||||
Prune *p = *it;
|
||||
int m = uid - p->mUid;
|
||||
if (m == 0) {
|
||||
if (p->mPid == p->pid_all) {
|
||||
break;
|
||||
}
|
||||
if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
|
||||
it = list->erase(it);
|
||||
continue;
|
||||
}
|
||||
m = pid - p->mPid;
|
||||
}
|
||||
if (m >= 0) {
|
||||
if (m > 0) {
|
||||
list->insert(it, new Prune(uid,pid));
|
||||
}
|
||||
break;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
if (it == list->end()) {
|
||||
list->push_back(new Prune(uid,pid));
|
||||
}
|
||||
if (!*str) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PruneList::format(char **strp) {
|
||||
if (*strp) {
|
||||
free(*strp);
|
||||
*strp = NULL;
|
||||
}
|
||||
|
||||
static const char nice_format[] = " %s";
|
||||
const char *fmt = nice_format + 1;
|
||||
|
||||
android::String8 string;
|
||||
|
||||
if (mWorstUidEnabled) {
|
||||
string.setTo("~!");
|
||||
fmt = nice_format;
|
||||
}
|
||||
|
||||
PruneCollection::iterator it;
|
||||
|
||||
for (it = mNice.begin(); it != mNice.end(); ++it) {
|
||||
char *a = NULL;
|
||||
(*it)->format(&a);
|
||||
|
||||
string.appendFormat(fmt, a);
|
||||
fmt = nice_format;
|
||||
|
||||
free(a);
|
||||
}
|
||||
|
||||
static const char naughty_format[] = " ~%s";
|
||||
fmt = naughty_format + (*fmt != ' ');
|
||||
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
|
||||
char *a = NULL;
|
||||
(*it)->format(&a);
|
||||
|
||||
string.appendFormat(fmt, a);
|
||||
fmt = naughty_format;
|
||||
|
||||
free(a);
|
||||
}
|
||||
|
||||
*strp = strdup(string.string());
|
||||
}
|
||||
|
||||
// ToDo: Lists are in sorted order, Prune->cmp() returns + or -
|
||||
// If there is scaling issues, resort to a better algorithm than linear
|
||||
// based on these assumptions.
|
||||
|
||||
bool PruneList::naughty(LogBufferElement *element) {
|
||||
PruneCollection::iterator it;
|
||||
for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
|
||||
if (!(*it)->cmp(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PruneList::nice(LogBufferElement *element) {
|
||||
PruneCollection::iterator it;
|
||||
for (it = mNice.begin(); it != mNice.end(); ++it) {
|
||||
if (!(*it)->cmp(element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USERDEBUG_BUILD
|
71
logd/LogWhiteBlackList.h
Normal file
71
logd/LogWhiteBlackList.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LOGD_LOG_WHITE_BLACK_LIST_H__
|
||||
#define _LOGD_LOG_WHITE_BLACK_LIST_H__
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <utils/List.h>
|
||||
|
||||
#include <LogBufferElement.h>
|
||||
|
||||
// White and Blacklist
|
||||
|
||||
class Prune {
|
||||
friend class PruneList;
|
||||
|
||||
const uid_t mUid;
|
||||
const pid_t mPid;
|
||||
int cmp(uid_t uid, pid_t pid) const;
|
||||
|
||||
public:
|
||||
static const uid_t uid_all = (uid_t) -1;
|
||||
static const pid_t pid_all = (pid_t) -1;
|
||||
|
||||
Prune(uid_t uid, pid_t pid);
|
||||
|
||||
uid_t getUid() const { return mUid; }
|
||||
pid_t getPid() const { return mPid; }
|
||||
|
||||
int cmp(LogBufferElement *e) const { return cmp(e->getUid(), e->getPid()); }
|
||||
|
||||
// *strp is malloc'd, use free to release
|
||||
void format(char **strp);
|
||||
};
|
||||
|
||||
typedef android::List<Prune *> PruneCollection;
|
||||
|
||||
class PruneList {
|
||||
PruneCollection mNaughty;
|
||||
PruneCollection mNice;
|
||||
bool mWorstUidEnabled;
|
||||
|
||||
public:
|
||||
PruneList();
|
||||
~PruneList();
|
||||
|
||||
int init(char *str);
|
||||
|
||||
bool naughty(LogBufferElement *element);
|
||||
bool nice(LogBufferElement *element);
|
||||
bool worstUidEnabled() const { return mWorstUidEnabled; }
|
||||
|
||||
// *strp is malloc'd, use free to release
|
||||
void format(char **strp);
|
||||
};
|
||||
|
||||
#endif // _LOGD_LOG_WHITE_BLACK_LIST_H__
|
Loading…
Reference in a new issue