Merge changes from topic 'enable_persist_kernel_log' into nyc-mr1-dev

* changes:
  logcatd: trampoline persist.logd.logpersistd to logd.logpersistd
  logcatd: add stop and clear actions
  logcatd: Do not su for setprop
  logcat: allow comma-separate list of buffers
  logcat: clear when specifying file output
  logcat: Adjust help to make it more meaningful
This commit is contained in:
Thierry Strudel 2016-07-21 04:07:22 +00:00 committed by Android (Google) Code Review
commit 56efe020b7
5 changed files with 342 additions and 188 deletions

View file

@ -278,61 +278,59 @@ static void show_help(const char *cmd)
fprintf(stderr,"Usage: %s [options] [filterspecs]\n", cmd);
fprintf(stderr, "options include:\n"
" -s Set default filter to silent.\n"
" Like specifying filterspec '*:S'\n"
" -f <filename> Log to file. Default is stdout\n"
" --file=<filename>\n"
" -r <kbytes> Rotate log every kbytes. Requires -f\n"
" --rotate-kbytes=<kbytes>\n"
" -n <count> Sets max number of rotated logs to <count>, default 4\n"
" --rotate-count=<count>\n"
" -v <format> Sets the log print format, where <format> is:\n"
" --format=<format>\n"
" brief color epoch long monotonic printable process raw\n"
" tag thread threadtime time uid usec UTC year zone\n\n"
" -D print dividers between each log buffer\n"
" --dividers\n"
" -c clear (flush) the entire log and exit\n"
" --clear\n"
" -d dump the log and then exit (don't block)\n"
" -e <expr> only print lines where the log message matches <expr>\n"
" --regex <expr> where <expr> is a regular expression\n"
" -m <count> quit after printing <count> lines. This is meant to be\n"
" --max-count=<count> paired with --regex, but will work on its own.\n"
" --print paired with --regex and --max-count to let content bypass\n"
" -s Set default filter to silent. Equivalent to filterspec '*:S'\n"
" -f <file>, --file=<file> Log to file. Default is stdout\n"
" -r <kbytes>, --rotate-kbytes=<kbytes>\n"
" Rotate log every kbytes. Requires -f option\n"
" -n <count>, --rotate-count=<count>\n"
" Sets max number of rotated logs to <count>, default 4\n"
" -v <format>, --format=<format>\n"
" Sets the log print format, where <format> is:\n"
" brief color epoch long monotonic printable process raw\n"
" tag thread threadtime time uid usec UTC year zone\n"
" -D, --dividers Print dividers between each log buffer\n"
" -c, --clear Clear (flush) the entire log and exit\n"
" if Log to File specified, clear fileset instead\n"
" -d Dump the log and then exit (don't block)\n"
" -e <expr>, --regex=<expr>\n"
" Only print lines where the log message matches <expr>\n"
" where <expr> is a regular expression\n"
// Leave --head undocumented as alias for -m
" -m <count>, --max-count=<count>\n"
" Quit after printing <count> lines. This is meant to be\n"
" paired with --regex, but will work on its own.\n"
" --print Paired with --regex and --max-count to let content bypass\n"
" regex filter but still stop at number of matches.\n"
" -t <count> print only the most recent <count> lines (implies -d)\n"
" -t '<time>' print most recent lines since specified time (implies -d)\n"
" -T <count> print only the most recent <count> lines (does not imply -d)\n"
" -T '<time>' print most recent lines since specified time (not imply -d)\n"
// Leave --tail undocumented as alias for -t
" -t <count> Print only the most recent <count> lines (implies -d)\n"
" -t '<time>' Print most recent lines since specified time (implies -d)\n"
" -T <count> Print only the most recent <count> lines (does not imply -d)\n"
" -T '<time>' Print most recent lines since specified time (not imply -d)\n"
" count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n"
" 'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n"
" -g get the size of the log's ring buffer and exit\n"
" --buffer-size\n"
" -G <size> set size of log ring buffer, may suffix with K or M.\n"
" --buffer-size=<size>\n"
" -L dump logs from prior to last reboot\n"
" --last\n"
" -g, --buffer-size Get the size of the ring buffer.\n"
" -G <size>, --buffer-size=<size>\n"
" Set size of log ring buffer, may suffix with K or M.\n"
" -L, -last Dump logs from prior to last reboot\n"
// Leave security (Device Owner only installations) and
// kernel (userdebug and eng) buffers undocumented.
" -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n"
" --buffer=<buffer> 'events', 'crash', 'default' or 'all'. Multiple -b\n"
" parameters are allowed and results are interleaved. The\n"
" default is -b main -b system -b crash.\n"
" -B output the log in binary.\n"
" --binary\n"
" -S output statistics.\n"
" --statistics\n"
" -p print prune white and ~black list. Service is specified as\n"
" --prune UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n"
" -b <buffer>, --buffer=<buffer> Request alternate ring buffer, 'main',\n"
" 'system', 'radio', 'events', 'crash', 'default' or 'all'.\n"
" Multiple -b parameters or comma separated list of buffers are\n"
" allowed. Buffers interleaved. Default -b main,system,crash.\n"
" -B, --binary Output the log in binary.\n"
" -S, --statistics Output statistics.\n"
" -p, --prune Print prune white and ~black list. Service is specified as\n"
" UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n"
" with ~, otherwise weighed for longevity if unadorned. All\n"
" other pruning activity is oldest first. Special case ~!\n"
" represents an automatic quicker pruning for the noisiest\n"
" UID as determined by the current statistics.\n"
" -P '<list> ...' set prune white and ~black list, using same format as\n"
" --prune='<list> ...' printed above. Must be quoted.\n"
" -P '<list> ...', --prune='<list> ...'\n"
" Set prune white and ~black list, using same format as\n"
" listed above. Must be quoted.\n"
" --pid=<pid> Only prints logs from the given pid.\n"
// Check ANDROID_LOG_WRAP_DEFAULT_TIMEOUT value
// Check ANDROID_LOG_WRAP_DEFAULT_TIMEOUT value for match to 2 hours
" --wrap Sleep for 2 hours or when buffer about to wrap whichever\n"
" comes first. Improves efficiency of polling by providing\n"
" an about-to-wrap wakeup.\n");
@ -765,111 +763,63 @@ int main(int argc, char **argv)
break;
case 'b': {
if (strcmp(optarg, "default") == 0) {
for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
switch (i) {
case LOG_ID_SECURITY:
case LOG_ID_EVENTS:
continue;
case LOG_ID_MAIN:
case LOG_ID_SYSTEM:
case LOG_ID_CRASH:
break;
default:
continue;
}
unsigned idMask = 0;
while ((optarg = strtok(optarg, ",:; \t\n\r\f")) != NULL) {
if (strcmp(optarg, "default") == 0) {
idMask |= (1 << LOG_ID_MAIN) |
(1 << LOG_ID_SYSTEM) |
(1 << LOG_ID_CRASH);
} else if (strcmp(optarg, "all") == 0) {
idMask = (unsigned)-1;
} else {
log_id_t log_id = android_name_to_log_id(optarg);
const char *name = android_log_id_to_name(log_id);
const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
if (log_id != (log_id_t)i) {
continue;
if (strcmp(name, optarg) != 0) {
logcat_panic(true, "unknown buffer %s\n", optarg);
}
bool found = false;
for (dev = devices; dev; dev = dev->next) {
if (!strcmp(optarg, dev->device)) {
found = true;
break;
}
if (!dev->next) {
break;
}
}
if (found) {
break;
}
log_device_t* d = new log_device_t(name, false);
if (dev) {
dev->next = d;
dev = d;
} else {
devices = dev = d;
}
g_devCount++;
idMask |= (1 << log_id);
}
break;
optarg = NULL;
}
if (strcmp(optarg, "all") == 0) {
for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) {
const char *name = android_log_id_to_name((log_id_t)i);
log_id_t log_id = android_name_to_log_id(name);
if (log_id != (log_id_t)i) {
continue;
}
if (log_id != (log_id_t)i) {
continue;
}
if ((idMask & (1 << i)) == 0) {
continue;
}
bool found = false;
for (dev = devices; dev; dev = dev->next) {
if (!strcmp(optarg, dev->device)) {
found = true;
break;
}
if (!dev->next) {
break;
}
}
if (found) {
bool found = false;
for (dev = devices; dev; dev = dev->next) {
if (!strcmp(name, dev->device)) {
found = true;
break;
}
bool binary = !strcmp(name, "events") ||
!strcmp(name, "security");
log_device_t* d = new log_device_t(name, binary);
if (dev) {
dev->next = d;
dev = d;
} else {
devices = dev = d;
}
g_devCount++;
}
break;
}
bool binary = !(strcmp(optarg, "events") &&
strcmp(optarg, "security"));
if (devices) {
dev = devices;
while (dev->next) {
if (!strcmp(optarg, dev->device)) {
dev = NULL;
if (!dev->next) {
break;
}
dev = dev->next;
}
if (found) {
continue;
}
bool binary = !strcmp(name, "events") ||
!strcmp(name, "security");
log_device_t* d = new log_device_t(name, binary);
if (dev) {
dev->next = new log_device_t(optarg, binary);
dev->next = d;
dev = d;
} else {
devices = dev = d;
}
} else {
devices = new log_device_t(optarg, binary);
g_devCount++;
}
g_devCount++;
}
break;
@ -1084,7 +1034,35 @@ int main(int argc, char **argv)
}
if (clearLog) {
if (android_logger_clear(dev->logger)) {
if (g_outputFileName) {
int maxRotationCountDigits =
(g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0;
for (int i = g_maxRotatedLogs ; i >= 0 ; --i) {
char *file;
if (i == 0) {
asprintf(&file, "%s", g_outputFileName);
} else {
asprintf(&file, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i);
}
if (!file) {
perror("while clearing log files");
clearFail = clearFail ?: dev->device;
break;
}
err = unlink(file);
if (err < 0 && errno != ENOENT && clearFail == NULL) {
perror("while clearing log files");
clearFail = dev->device;
}
free(file);
}
} else if (android_logger_clear(dev->logger)) {
clearFail = clearFail ?: dev->device;
}
}

View file

@ -1,11 +1,62 @@
#
# init scriptures for logcatd persistent logging.
#
# Make sure any property changes are only performed with /data mounted, after
# post-fs-data state because otherwise behavior is undefined. The exceptions
# are device adjustments for logcatd service properties (persist.* overrides
# notwithstanding) for logd.logpersistd.size and logd.logpersistd.buffer.
# persist to non-persistent trampolines to permit device properties can be
# overridden when /data mounts, or during runtime.
on property:persist.logd.logpersistd.size=256
setprop persist.logd.logpersistd.size ""
setprop logd.logpersistd.size ""
on property:persist.logd.logpersistd.size=*
# expect /init to report failure if property empty (default)
setprop logd.logpersistd.size ${persist.logd.logpersistd.size}
on property:persist.logd.logpersistd.buffer=all
setprop persist.logd.logpersistd.buffer ""
setprop logd.logpersistd.buffer ""
on property:persist.logd.logpersistd.buffer=*
# expect /init to report failure if property empty (default)
setprop logd.logpersistd.buffer ${persist.logd.logpersistd.buffer}
on property:persist.logd.logpersistd=logcatd
setprop logd.logpersistd logcatd
# enable, prep and start logcatd service
on load_persist_props_action
setprop logd.logpersistd.enable true
on property:logd.logpersistd.enable=true && property:logd.logpersistd=logcatd
# all exec/services are called with umask(077), so no gain beyond 0700
mkdir /data/misc/logd 0700 logd log
# logd for write to /data/misc/logd, log group for read from pstore (-L)
exec - logd log -- /system/bin/logcat -L -b ${persist.logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${persist.logd.logpersistd.size:-256}
exec - logd log -- /system/bin/logcat -L -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
start logcatd
service logcatd /system/bin/logcat -b ${persist.logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${persist.logd.logpersistd.size:-256}
# stop logcatd service and clear data
on property:logd.logpersistd.enable=true && property:logd.logpersistd=clear
setprop persist.logd.logpersistd ""
stop logcatd
# logd for clear of only our files in /data/misc/logd
exec - logd log -- /system/bin/logcat -c -f /data/misc/logd/logcat -n ${logd.logpersistd.size:-256}
setprop logd.logpersistd ""
# stop logcatd service
on property:logd.logpersistd=stop
setprop persist.logd.logpersistd ""
stop logcatd
setprop logd.logpersistd ""
on property:logd.logpersistd.enable=false
stop logcatd
# logcatd service
service logcatd /system/bin/logcat -b ${logd.logpersistd.buffer:-all} -v threadtime -v usec -v printable -D -f /data/misc/logd/logcat -r 1024 -n ${logd.logpersistd.size:-256}
class late_start
disabled
# logd for write to /data/misc/logd, log group for read from log daemon

View file

@ -8,8 +8,16 @@ userdebug|eng) ;;
;;
esac
data=/data/misc/logd
property=persist.logd.logpersistd
case `getprop ${property#persist.}.enable` in
true) ;;
*) echo "${progname} - Disabled"
exit 1
;;
esac
data=/data/misc/logd
service=logcatd
size_default=256
buffer_default=all
@ -69,14 +77,11 @@ case ${progname} in
su logd xargs cat
;;
*.start)
current_buffer="`getprop ${property}.buffer`"
current_size="`getprop ${property}.size`"
if [ "${service}" = "`getprop ${property}`" ]; then
current_buffer="`getprop ${property#persist.}.buffer`"
current_size="`getprop ${property#persist.}.size`"
if [ "${service}" = "`getprop ${property#persist.}`" ]; then
if [ "true" = "${clear}" ]; then
su root stop ${service}
su root setprop ${property} ""
# 20ms done, guarantees content stop before rm
sleep 1
setprop ${property#persist.} "clear"
elif [ "${buffer}|${size}" != "${current_buffer}|${current_size}" ]; then
echo "ERROR: Changing existing collection parameters from" >&2
if [ "${buffer}" != "${current_buffer}" ]; then
@ -98,21 +103,31 @@ case ${progname} in
echo " To blindly override and retain data, ${progname%.*}.stop first." >&2
exit 1
fi
fi
if [ "true" = "${clear}" ]; then
su logd,misc rm -rf "${data}"
elif [ "true" = "${clear}" ]; then
setprop ${property#persist.} "clear"
fi
if [ -n "${buffer}${current_buffer}" ]; then
su root setprop ${property}.buffer "${buffer}"
setprop ${property}.buffer "${buffer}"
if [ -z "${buffer}" ]; then
# deal with trampoline for empty properties
setprop ${property#persist.}.buffer ""
fi
fi
if [ -n "${size}${current_size}" ]; then
su root setprop ${property}.size "${size}"
setprop ${property}.size "${size}"
if [ -z "${size}" ]; then
# deal with trampoline for empty properties
setprop ${property#persist.}.size ""
fi
fi
while [ "clear" = "`getprop ${property#persist.}`" ]; do
continue
done
# ${service}.rc does the heavy lifting with the following trigger
su root setprop ${property} ${service}
getprop ${property}
setprop ${property} ${service}
# 20ms done, to permit process feedback check
sleep 1
getprop ${property#persist.}
# also generate an error return code if not found running, bonus
ps -t | grep "${data##*/}.*${service%d}"
;;
@ -120,19 +135,24 @@ case ${progname} in
if [ -n "${size}${buffer}" ]; then
echo "WARNING: Can not use --size or --buffer with ${progname%.*}.stop" >&2
fi
su root stop ${service}
su root setprop ${property} ""
if [ -n "`getprop ${property}.buffer`" ]; then
su root setprop ${property}.buffer ""
fi
if [ -n "`getprop ${property}.size`" ]; then
su root setprop ${property}.size ""
fi
if [ "true" = "${clear}" ]; then
# 20ms done, guarantees content stop before rm
sleep 1
su logd,misc rm -rf "${data}"
setprop ${property} "clear"
else
setprop ${property} "stop"
fi
if [ -n "`getprop ${property#persist.}.buffer`" ]; then
setprop ${property}.buffer ""
# deal with trampoline for empty properties
setprop ${property#persist.}.buffer ""
fi
if [ -n "`getprop ${property#persist.}.size`" ]; then
setprop ${property}.size ""
# deal with trampoline for empty properties
setprop ${property#persist.}.size ""
fi
while [ "clear" = "`getprop ${property#persist.}`" ]; do
continue
done
;;
*)
echo "ERROR: Unexpected command ${0##*/} ${args}" >&2

View file

@ -28,6 +28,8 @@
#include <log/logger.h>
#include <log/log_read.h>
#define BIG_BUFFER (5 * 1024)
// enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and
// non-syscall libs. Since we are only using this in the emergency of
// a signal to stuff a terminating code into the logs, we will spin rather
@ -52,7 +54,7 @@ TEST(logcat, buckets) {
"logcat -b radio -b events -b system -b main -d 2>/dev/null",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int ids = 0;
int count = 0;
@ -100,7 +102,7 @@ TEST(logcat, year) {
"logcat -v long -v year -b all -t 3 2>/dev/null",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
@ -163,7 +165,7 @@ TEST(logcat, tz) {
"logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
count = 0;
@ -187,7 +189,7 @@ TEST(logcat, ntz) {
"logcat -v long -v America/Los_Angeles -v zone -b all -t 3 2>/dev/null",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
@ -207,7 +209,7 @@ void do_tail(int num) {
int count;
do {
char buffer[5120];
char buffer[BIG_BUFFER];
snprintf(buffer, sizeof(buffer),
"logcat -v long -b radio -b events -b system -b main -t %d 2>/dev/null",
@ -250,7 +252,7 @@ TEST(logcat, tail_time) {
ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r")));
char buffer[5120];
char buffer[BIG_BUFFER];
char *last_timestamp = NULL;
char *first_timestamp = NULL;
int count = 0;
@ -313,7 +315,7 @@ TEST(logcat, End_to_End) {
"logcat -v brief -b events -t 100 2>/dev/null",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
@ -337,15 +339,17 @@ TEST(logcat, End_to_End) {
ASSERT_EQ(1, count);
}
TEST(logcat, get_size) {
int get_groups(const char *cmd) {
FILE *fp;
// NB: crash log only available in user space
ASSERT_TRUE(NULL != (fp = popen(
"logcat -v brief -b radio -b events -b system -b main -g 2>/dev/null",
"r")));
EXPECT_TRUE(NULL != (fp = popen(cmd, "r")));
char buffer[5120];
if (fp == NULL) {
return 0;
}
char buffer[BIG_BUFFER];
int count = 0;
@ -405,7 +409,23 @@ TEST(logcat, get_size) {
pclose(fp);
ASSERT_EQ(4, count);
return count;
}
TEST(logcat, get_size) {
ASSERT_EQ(4, get_groups(
"logcat -v brief -b radio -b events -b system -b main -g 2>/dev/null"));
}
// duplicate test for get_size, but use comma-separated list of buffers
TEST(logcat, multiple_buffer) {
ASSERT_EQ(4, get_groups(
"logcat -v brief -b radio,events,system,main -g 2>/dev/null"));
}
TEST(logcat, bad_buffer) {
ASSERT_EQ(0, get_groups(
"logcat -v brief -b radio,events,bogo,system,main -g 2>/dev/null"));
}
static void caught_blocking(int /*signum*/)
@ -434,7 +454,7 @@ TEST(logcat, blocking) {
" logcat -v brief -b events 2>&1",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
@ -503,7 +523,7 @@ TEST(logcat, blocking_tail) {
" logcat -v brief -b events -T 5 2>&1",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
@ -566,7 +586,7 @@ TEST(logcat, logrotate) {
FILE *fp;
EXPECT_TRUE(NULL != (fp = popen(command, "r")));
if (fp) {
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
@ -609,7 +629,7 @@ TEST(logcat, logrotate_suffix) {
FILE *fp;
EXPECT_TRUE(NULL != (fp = popen(command, "r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int log_file_count = 0;
while (fgets(buffer, sizeof(buffer), fp)) {
@ -751,6 +771,82 @@ TEST(logcat, logrotate_continue) {
EXPECT_FALSE(system(command));
}
TEST(logcat, logrotate_clear) {
static const char tmp_out_dir_form[] = "/data/local/tmp/logcat.logrotate.XXXXXX";
char tmp_out_dir[sizeof(tmp_out_dir_form)];
ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form)));
static const char log_filename[] = "log.txt";
static const unsigned num_val = 32;
static const char logcat_cmd[] = "logcat -b all -d -f %s/%s -n %d -r 1";
static const char clear_cmd[] = " -c";
static const char cleanup_cmd[] = "rm -rf %s";
char command[sizeof(tmp_out_dir) + sizeof(logcat_cmd) + sizeof(log_filename) + sizeof(clear_cmd) + 32];
// Run command with all data
{
snprintf(command, sizeof(command) - sizeof(clear_cmd),
logcat_cmd, tmp_out_dir, log_filename, num_val);
int ret;
EXPECT_FALSE((ret = system(command)));
if (ret) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
EXPECT_NE(nullptr, dir);
if (!dir) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
struct dirent *entry;
unsigned count = 0;
while ((entry = readdir(dir.get()))) {
if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
continue;
}
++count;
}
EXPECT_EQ(count, num_val + 1);
}
{
// Now with -c option tacked onto the end
strcat(command, clear_cmd);
int ret;
EXPECT_FALSE((ret = system(command)));
if (ret) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir);
EXPECT_NE(nullptr, dir);
if (!dir) {
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
return;
}
struct dirent *entry;
unsigned count = 0;
while ((entry = readdir(dir.get()))) {
if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) {
continue;
}
fprintf(stderr, "Found %s/%s!!!\n", tmp_out_dir, entry->d_name);
++count;
}
EXPECT_EQ(count, 0U);
}
snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir);
EXPECT_FALSE(system(command));
}
TEST(logcat, logrotate_nodir) {
// expect logcat to error out on writing content and exit(1) for nodir
EXPECT_EQ(W_EXITCODE(1, 0),
@ -783,7 +879,7 @@ TEST(logcat, blocking_clear) {
" logcat -v brief -b events 2>&1",
"r")));
char buffer[5120];
char buffer[BIG_BUFFER];
int count = 0;
@ -844,7 +940,7 @@ static bool get_white_black(char **list) {
return false;
}
char buffer[5120];
char buffer[BIG_BUFFER];
while (fgets(buffer, sizeof(buffer), fp)) {
char *hold = *list;
@ -873,7 +969,7 @@ static bool get_white_black(char **list) {
static bool set_white_black(const char *list) {
FILE *fp;
char buffer[5120];
char buffer[BIG_BUFFER];
snprintf(buffer, sizeof(buffer), "logcat -P '%s' 2>&1", list ? list : "");
fp = popen(buffer, "r");
@ -935,7 +1031,7 @@ TEST(logcat, regex) {
FILE *fp;
int count = 0;
char buffer[5120];
char buffer[BIG_BUFFER];
snprintf(buffer, sizeof(buffer), "logcat --pid %d -d -e logcat_test_a+b", getpid());
@ -968,7 +1064,7 @@ TEST(logcat, maxcount) {
FILE *fp;
int count = 0;
char buffer[5120];
char buffer[BIG_BUFFER];
snprintf(buffer, sizeof(buffer), "logcat --pid %d -d --max-count 3", getpid());

View file

@ -1,4 +1,4 @@
The properties that logd responds to are:
The properties that logd and friends react to are:
name type default description
ro.logd.auditd bool true Enable selinux audit daemon
@ -10,8 +10,16 @@ ro.logd.kernel bool+ svelte+ Enable klogd daemon
ro.logd.statistics bool+ svelte+ Enable logcat -S statistics.
ro.build.type string if user, logd.statistics &
ro.logd.kernel default false.
logd.logpersistd.enable bool auto Safe to start logpersist daemon service
logd.logpersistd string persist Enable logpersist daemon, "logcatd"
turns on logcat -f in logd context.
Responds to logcatd, clear and stop.
logd.logpersistd.buffer persist logpersistd buffers to collect
logd.logpersistd.size persist logpersistd size in MB
persist.logd.logpersistd string Enable logpersist daemon, "logcatd"
turns on logcat -f in logd context
turns on logcat -f in logd context.
persist.logd.logpersistd.buffer all logpersistd buffers to collect
persist.logd.logpersistd.size 256 logpersistd size in MB
persist.logd.size number ro Global default size of the buffer for
all log ids at initial startup, at
runtime use: logcat -b all -G <value>
@ -45,6 +53,7 @@ log.tag.<tag> string persist The <tag> specific logging level.
persist.log.tag.<tag> string build default for log.tag.<tag>
NB:
- auto - managed by /init
- bool+ - "true", "false" and comma separated list of "eng" (forced false if
ro.build.type is "user") or "svelte" (forced false if ro.config.low_ram is
true).