system/corennnnn
修訂 | 56efe020b74d12456e96db8bd1937e15a97403eb (tree) |
---|---|
時間 | 2016-07-21 13:07:25 |
作者 | Thierry Strudel <tstrudel@goog...> |
Commiter | Android (Google) Code Review |
Merge changes from topic 'enable_persist_kernel_log' into nyc-mr1-dev
* changes:
@@ -278,61 +278,59 @@ static void show_help(const char *cmd) | ||
278 | 278 | fprintf(stderr,"Usage: %s [options] [filterspecs]\n", cmd); |
279 | 279 | |
280 | 280 | fprintf(stderr, "options include:\n" |
281 | - " -s Set default filter to silent.\n" | |
282 | - " Like specifying filterspec '*:S'\n" | |
283 | - " -f <filename> Log to file. Default is stdout\n" | |
284 | - " --file=<filename>\n" | |
285 | - " -r <kbytes> Rotate log every kbytes. Requires -f\n" | |
286 | - " --rotate-kbytes=<kbytes>\n" | |
287 | - " -n <count> Sets max number of rotated logs to <count>, default 4\n" | |
288 | - " --rotate-count=<count>\n" | |
289 | - " -v <format> Sets the log print format, where <format> is:\n" | |
290 | - " --format=<format>\n" | |
291 | - " brief color epoch long monotonic printable process raw\n" | |
292 | - " tag thread threadtime time uid usec UTC year zone\n\n" | |
293 | - " -D print dividers between each log buffer\n" | |
294 | - " --dividers\n" | |
295 | - " -c clear (flush) the entire log and exit\n" | |
296 | - " --clear\n" | |
297 | - " -d dump the log and then exit (don't block)\n" | |
298 | - " -e <expr> only print lines where the log message matches <expr>\n" | |
299 | - " --regex <expr> where <expr> is a regular expression\n" | |
300 | - " -m <count> quit after printing <count> lines. This is meant to be\n" | |
301 | - " --max-count=<count> paired with --regex, but will work on its own.\n" | |
302 | - " --print paired with --regex and --max-count to let content bypass\n" | |
281 | + " -s Set default filter to silent. Equivalent to filterspec '*:S'\n" | |
282 | + " -f <file>, --file=<file> Log to file. Default is stdout\n" | |
283 | + " -r <kbytes>, --rotate-kbytes=<kbytes>\n" | |
284 | + " Rotate log every kbytes. Requires -f option\n" | |
285 | + " -n <count>, --rotate-count=<count>\n" | |
286 | + " Sets max number of rotated logs to <count>, default 4\n" | |
287 | + " -v <format>, --format=<format>\n" | |
288 | + " Sets the log print format, where <format> is:\n" | |
289 | + " brief color epoch long monotonic printable process raw\n" | |
290 | + " tag thread threadtime time uid usec UTC year zone\n" | |
291 | + " -D, --dividers Print dividers between each log buffer\n" | |
292 | + " -c, --clear Clear (flush) the entire log and exit\n" | |
293 | + " if Log to File specified, clear fileset instead\n" | |
294 | + " -d Dump the log and then exit (don't block)\n" | |
295 | + " -e <expr>, --regex=<expr>\n" | |
296 | + " Only print lines where the log message matches <expr>\n" | |
297 | + " where <expr> is a regular expression\n" | |
298 | + // Leave --head undocumented as alias for -m | |
299 | + " -m <count>, --max-count=<count>\n" | |
300 | + " Quit after printing <count> lines. This is meant to be\n" | |
301 | + " paired with --regex, but will work on its own.\n" | |
302 | + " --print Paired with --regex and --max-count to let content bypass\n" | |
303 | 303 | " regex filter but still stop at number of matches.\n" |
304 | - " -t <count> print only the most recent <count> lines (implies -d)\n" | |
305 | - " -t '<time>' print most recent lines since specified time (implies -d)\n" | |
306 | - " -T <count> print only the most recent <count> lines (does not imply -d)\n" | |
307 | - " -T '<time>' print most recent lines since specified time (not imply -d)\n" | |
304 | + // Leave --tail undocumented as alias for -t | |
305 | + " -t <count> Print only the most recent <count> lines (implies -d)\n" | |
306 | + " -t '<time>' Print most recent lines since specified time (implies -d)\n" | |
307 | + " -T <count> Print only the most recent <count> lines (does not imply -d)\n" | |
308 | + " -T '<time>' Print most recent lines since specified time (not imply -d)\n" | |
308 | 309 | " count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'\n" |
309 | 310 | " 'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format\n" |
310 | - " -g get the size of the log's ring buffer and exit\n" | |
311 | - " --buffer-size\n" | |
312 | - " -G <size> set size of log ring buffer, may suffix with K or M.\n" | |
313 | - " --buffer-size=<size>\n" | |
314 | - " -L dump logs from prior to last reboot\n" | |
315 | - " --last\n" | |
311 | + " -g, --buffer-size Get the size of the ring buffer.\n" | |
312 | + " -G <size>, --buffer-size=<size>\n" | |
313 | + " Set size of log ring buffer, may suffix with K or M.\n" | |
314 | + " -L, -last Dump logs from prior to last reboot\n" | |
316 | 315 | // Leave security (Device Owner only installations) and |
317 | 316 | // kernel (userdebug and eng) buffers undocumented. |
318 | - " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio',\n" | |
319 | - " --buffer=<buffer> 'events', 'crash', 'default' or 'all'. Multiple -b\n" | |
320 | - " parameters are allowed and results are interleaved. The\n" | |
321 | - " default is -b main -b system -b crash.\n" | |
322 | - " -B output the log in binary.\n" | |
323 | - " --binary\n" | |
324 | - " -S output statistics.\n" | |
325 | - " --statistics\n" | |
326 | - " -p print prune white and ~black list. Service is specified as\n" | |
327 | - " --prune UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n" | |
317 | + " -b <buffer>, --buffer=<buffer> Request alternate ring buffer, 'main',\n" | |
318 | + " 'system', 'radio', 'events', 'crash', 'default' or 'all'.\n" | |
319 | + " Multiple -b parameters or comma separated list of buffers are\n" | |
320 | + " allowed. Buffers interleaved. Default -b main,system,crash.\n" | |
321 | + " -B, --binary Output the log in binary.\n" | |
322 | + " -S, --statistics Output statistics.\n" | |
323 | + " -p, --prune Print prune white and ~black list. Service is specified as\n" | |
324 | + " UID, UID/PID or /PID. Weighed for quicker pruning if prefix\n" | |
328 | 325 | " with ~, otherwise weighed for longevity if unadorned. All\n" |
329 | 326 | " other pruning activity is oldest first. Special case ~!\n" |
330 | 327 | " represents an automatic quicker pruning for the noisiest\n" |
331 | 328 | " UID as determined by the current statistics.\n" |
332 | - " -P '<list> ...' set prune white and ~black list, using same format as\n" | |
333 | - " --prune='<list> ...' printed above. Must be quoted.\n" | |
329 | + " -P '<list> ...', --prune='<list> ...'\n" | |
330 | + " Set prune white and ~black list, using same format as\n" | |
331 | + " listed above. Must be quoted.\n" | |
334 | 332 | " --pid=<pid> Only prints logs from the given pid.\n" |
335 | - // Check ANDROID_LOG_WRAP_DEFAULT_TIMEOUT value | |
333 | + // Check ANDROID_LOG_WRAP_DEFAULT_TIMEOUT value for match to 2 hours | |
336 | 334 | " --wrap Sleep for 2 hours or when buffer about to wrap whichever\n" |
337 | 335 | " comes first. Improves efficiency of polling by providing\n" |
338 | 336 | " an about-to-wrap wakeup.\n"); |
@@ -765,111 +763,63 @@ int main(int argc, char **argv) | ||
765 | 763 | break; |
766 | 764 | |
767 | 765 | case 'b': { |
768 | - if (strcmp(optarg, "default") == 0) { | |
769 | - for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { | |
770 | - switch (i) { | |
771 | - case LOG_ID_SECURITY: | |
772 | - case LOG_ID_EVENTS: | |
773 | - continue; | |
774 | - case LOG_ID_MAIN: | |
775 | - case LOG_ID_SYSTEM: | |
776 | - case LOG_ID_CRASH: | |
777 | - break; | |
778 | - default: | |
779 | - continue; | |
780 | - } | |
781 | - | |
782 | - const char *name = android_log_id_to_name((log_id_t)i); | |
783 | - log_id_t log_id = android_name_to_log_id(name); | |
784 | - | |
785 | - if (log_id != (log_id_t)i) { | |
786 | - continue; | |
787 | - } | |
788 | - | |
789 | - bool found = false; | |
790 | - for (dev = devices; dev; dev = dev->next) { | |
791 | - if (!strcmp(optarg, dev->device)) { | |
792 | - found = true; | |
793 | - break; | |
794 | - } | |
795 | - if (!dev->next) { | |
796 | - break; | |
797 | - } | |
798 | - } | |
799 | - if (found) { | |
800 | - break; | |
801 | - } | |
802 | - | |
803 | - log_device_t* d = new log_device_t(name, false); | |
766 | + unsigned idMask = 0; | |
767 | + while ((optarg = strtok(optarg, ",:; \t\n\r\f")) != NULL) { | |
768 | + if (strcmp(optarg, "default") == 0) { | |
769 | + idMask |= (1 << LOG_ID_MAIN) | | |
770 | + (1 << LOG_ID_SYSTEM) | | |
771 | + (1 << LOG_ID_CRASH); | |
772 | + } else if (strcmp(optarg, "all") == 0) { | |
773 | + idMask = (unsigned)-1; | |
774 | + } else { | |
775 | + log_id_t log_id = android_name_to_log_id(optarg); | |
776 | + const char *name = android_log_id_to_name(log_id); | |
804 | 777 | |
805 | - if (dev) { | |
806 | - dev->next = d; | |
807 | - dev = d; | |
808 | - } else { | |
809 | - devices = dev = d; | |
778 | + if (strcmp(name, optarg) != 0) { | |
779 | + logcat_panic(true, "unknown buffer %s\n", optarg); | |
810 | 780 | } |
811 | - g_devCount++; | |
781 | + idMask |= (1 << log_id); | |
812 | 782 | } |
813 | - break; | |
783 | + optarg = NULL; | |
814 | 784 | } |
815 | 785 | |
816 | - if (strcmp(optarg, "all") == 0) { | |
817 | - for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { | |
818 | - const char *name = android_log_id_to_name((log_id_t)i); | |
819 | - log_id_t log_id = android_name_to_log_id(name); | |
786 | + for (int i = LOG_ID_MIN; i < LOG_ID_MAX; ++i) { | |
787 | + const char *name = android_log_id_to_name((log_id_t)i); | |
788 | + log_id_t log_id = android_name_to_log_id(name); | |
820 | 789 | |
821 | - if (log_id != (log_id_t)i) { | |
822 | - continue; | |
823 | - } | |
790 | + if (log_id != (log_id_t)i) { | |
791 | + continue; | |
792 | + } | |
793 | + if ((idMask & (1 << i)) == 0) { | |
794 | + continue; | |
795 | + } | |
824 | 796 | |
825 | - bool found = false; | |
826 | - for (dev = devices; dev; dev = dev->next) { | |
827 | - if (!strcmp(optarg, dev->device)) { | |
828 | - found = true; | |
829 | - break; | |
830 | - } | |
831 | - if (!dev->next) { | |
832 | - break; | |
833 | - } | |
834 | - } | |
835 | - if (found) { | |
797 | + bool found = false; | |
798 | + for (dev = devices; dev; dev = dev->next) { | |
799 | + if (!strcmp(name, dev->device)) { | |
800 | + found = true; | |
836 | 801 | break; |
837 | 802 | } |
838 | - | |
839 | - bool binary = !strcmp(name, "events") || | |
840 | - !strcmp(name, "security"); | |
841 | - log_device_t* d = new log_device_t(name, binary); | |
842 | - | |
843 | - if (dev) { | |
844 | - dev->next = d; | |
845 | - dev = d; | |
846 | - } else { | |
847 | - devices = dev = d; | |
803 | + if (!dev->next) { | |
804 | + break; | |
848 | 805 | } |
849 | - g_devCount++; | |
850 | 806 | } |
851 | - break; | |
852 | - } | |
807 | + if (found) { | |
808 | + continue; | |
809 | + } | |
853 | 810 | |
854 | - bool binary = !(strcmp(optarg, "events") && | |
855 | - strcmp(optarg, "security")); | |
811 | + bool binary = !strcmp(name, "events") || | |
812 | + !strcmp(name, "security"); | |
813 | + log_device_t* d = new log_device_t(name, binary); | |
856 | 814 | |
857 | - if (devices) { | |
858 | - dev = devices; | |
859 | - while (dev->next) { | |
860 | - if (!strcmp(optarg, dev->device)) { | |
861 | - dev = NULL; | |
862 | - break; | |
863 | - } | |
864 | - dev = dev->next; | |
865 | - } | |
866 | 815 | if (dev) { |
867 | - dev->next = new log_device_t(optarg, binary); | |
816 | + dev->next = d; | |
817 | + dev = d; | |
818 | + } else { | |
819 | + devices = dev = d; | |
868 | 820 | } |
869 | - } else { | |
870 | - devices = new log_device_t(optarg, binary); | |
821 | + g_devCount++; | |
871 | 822 | } |
872 | - g_devCount++; | |
873 | 823 | } |
874 | 824 | break; |
875 | 825 |
@@ -1084,7 +1034,35 @@ int main(int argc, char **argv) | ||
1084 | 1034 | } |
1085 | 1035 | |
1086 | 1036 | if (clearLog) { |
1087 | - if (android_logger_clear(dev->logger)) { | |
1037 | + if (g_outputFileName) { | |
1038 | + int maxRotationCountDigits = | |
1039 | + (g_maxRotatedLogs > 0) ? (int) (floor(log10(g_maxRotatedLogs) + 1)) : 0; | |
1040 | + | |
1041 | + for (int i = g_maxRotatedLogs ; i >= 0 ; --i) { | |
1042 | + char *file; | |
1043 | + | |
1044 | + if (i == 0) { | |
1045 | + asprintf(&file, "%s", g_outputFileName); | |
1046 | + } else { | |
1047 | + asprintf(&file, "%s.%.*d", g_outputFileName, maxRotationCountDigits, i); | |
1048 | + } | |
1049 | + | |
1050 | + if (!file) { | |
1051 | + perror("while clearing log files"); | |
1052 | + clearFail = clearFail ?: dev->device; | |
1053 | + break; | |
1054 | + } | |
1055 | + | |
1056 | + err = unlink(file); | |
1057 | + | |
1058 | + if (err < 0 && errno != ENOENT && clearFail == NULL) { | |
1059 | + perror("while clearing log files"); | |
1060 | + clearFail = dev->device; | |
1061 | + } | |
1062 | + | |
1063 | + free(file); | |
1064 | + } | |
1065 | + } else if (android_logger_clear(dev->logger)) { | |
1088 | 1066 | clearFail = clearFail ?: dev->device; |
1089 | 1067 | } |
1090 | 1068 | } |
@@ -1,11 +1,62 @@ | ||
1 | +# | |
2 | +# init scriptures for logcatd persistent logging. | |
3 | +# | |
4 | +# Make sure any property changes are only performed with /data mounted, after | |
5 | +# post-fs-data state because otherwise behavior is undefined. The exceptions | |
6 | +# are device adjustments for logcatd service properties (persist.* overrides | |
7 | +# notwithstanding) for logd.logpersistd.size and logd.logpersistd.buffer. | |
8 | + | |
9 | +# persist to non-persistent trampolines to permit device properties can be | |
10 | +# overridden when /data mounts, or during runtime. | |
11 | +on property:persist.logd.logpersistd.size=256 | |
12 | + setprop persist.logd.logpersistd.size "" | |
13 | + setprop logd.logpersistd.size "" | |
14 | + | |
15 | +on property:persist.logd.logpersistd.size=* | |
16 | + # expect /init to report failure if property empty (default) | |
17 | + setprop logd.logpersistd.size ${persist.logd.logpersistd.size} | |
18 | + | |
19 | +on property:persist.logd.logpersistd.buffer=all | |
20 | + setprop persist.logd.logpersistd.buffer "" | |
21 | + setprop logd.logpersistd.buffer "" | |
22 | + | |
23 | +on property:persist.logd.logpersistd.buffer=* | |
24 | + # expect /init to report failure if property empty (default) | |
25 | + setprop logd.logpersistd.buffer ${persist.logd.logpersistd.buffer} | |
26 | + | |
1 | 27 | on property:persist.logd.logpersistd=logcatd |
28 | + setprop logd.logpersistd logcatd | |
29 | + | |
30 | +# enable, prep and start logcatd service | |
31 | +on load_persist_props_action | |
32 | + setprop logd.logpersistd.enable true | |
33 | + | |
34 | +on property:logd.logpersistd.enable=true && property:logd.logpersistd=logcatd | |
2 | 35 | # all exec/services are called with umask(077), so no gain beyond 0700 |
3 | 36 | mkdir /data/misc/logd 0700 logd log |
4 | 37 | # logd for write to /data/misc/logd, log group for read from pstore (-L) |
5 | - 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} | |
38 | + 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} | |
6 | 39 | start logcatd |
7 | 40 | |
8 | -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} | |
41 | +# stop logcatd service and clear data | |
42 | +on property:logd.logpersistd.enable=true && property:logd.logpersistd=clear | |
43 | + setprop persist.logd.logpersistd "" | |
44 | + stop logcatd | |
45 | + # logd for clear of only our files in /data/misc/logd | |
46 | + exec - logd log -- /system/bin/logcat -c -f /data/misc/logd/logcat -n ${logd.logpersistd.size:-256} | |
47 | + setprop logd.logpersistd "" | |
48 | + | |
49 | +# stop logcatd service | |
50 | +on property:logd.logpersistd=stop | |
51 | + setprop persist.logd.logpersistd "" | |
52 | + stop logcatd | |
53 | + setprop logd.logpersistd "" | |
54 | + | |
55 | +on property:logd.logpersistd.enable=false | |
56 | + stop logcatd | |
57 | + | |
58 | +# logcatd service | |
59 | +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} | |
9 | 60 | class late_start |
10 | 61 | disabled |
11 | 62 | # logd for write to /data/misc/logd, log group for read from log daemon |
@@ -8,8 +8,16 @@ userdebug|eng) ;; | ||
8 | 8 | ;; |
9 | 9 | esac |
10 | 10 | |
11 | -data=/data/misc/logd | |
12 | 11 | property=persist.logd.logpersistd |
12 | + | |
13 | +case `getprop ${property#persist.}.enable` in | |
14 | +true) ;; | |
15 | +*) echo "${progname} - Disabled" | |
16 | + exit 1 | |
17 | + ;; | |
18 | +esac | |
19 | + | |
20 | +data=/data/misc/logd | |
13 | 21 | service=logcatd |
14 | 22 | size_default=256 |
15 | 23 | buffer_default=all |
@@ -69,14 +77,11 @@ case ${progname} in | ||
69 | 77 | su logd xargs cat |
70 | 78 | ;; |
71 | 79 | *.start) |
72 | - current_buffer="`getprop ${property}.buffer`" | |
73 | - current_size="`getprop ${property}.size`" | |
74 | - if [ "${service}" = "`getprop ${property}`" ]; then | |
80 | + current_buffer="`getprop ${property#persist.}.buffer`" | |
81 | + current_size="`getprop ${property#persist.}.size`" | |
82 | + if [ "${service}" = "`getprop ${property#persist.}`" ]; then | |
75 | 83 | if [ "true" = "${clear}" ]; then |
76 | - su root stop ${service} | |
77 | - su root setprop ${property} "" | |
78 | - # 20ms done, guarantees content stop before rm | |
79 | - sleep 1 | |
84 | + setprop ${property#persist.} "clear" | |
80 | 85 | elif [ "${buffer}|${size}" != "${current_buffer}|${current_size}" ]; then |
81 | 86 | echo "ERROR: Changing existing collection parameters from" >&2 |
82 | 87 | if [ "${buffer}" != "${current_buffer}" ]; then |
@@ -98,21 +103,31 @@ case ${progname} in | ||
98 | 103 | echo " To blindly override and retain data, ${progname%.*}.stop first." >&2 |
99 | 104 | exit 1 |
100 | 105 | fi |
101 | - fi | |
102 | - if [ "true" = "${clear}" ]; then | |
103 | - su logd,misc rm -rf "${data}" | |
106 | + elif [ "true" = "${clear}" ]; then | |
107 | + setprop ${property#persist.} "clear" | |
104 | 108 | fi |
105 | 109 | if [ -n "${buffer}${current_buffer}" ]; then |
106 | - su root setprop ${property}.buffer "${buffer}" | |
110 | + setprop ${property}.buffer "${buffer}" | |
111 | + if [ -z "${buffer}" ]; then | |
112 | + # deal with trampoline for empty properties | |
113 | + setprop ${property#persist.}.buffer "" | |
114 | + fi | |
107 | 115 | fi |
108 | 116 | if [ -n "${size}${current_size}" ]; then |
109 | - su root setprop ${property}.size "${size}" | |
117 | + setprop ${property}.size "${size}" | |
118 | + if [ -z "${size}" ]; then | |
119 | + # deal with trampoline for empty properties | |
120 | + setprop ${property#persist.}.size "" | |
121 | + fi | |
110 | 122 | fi |
123 | + while [ "clear" = "`getprop ${property#persist.}`" ]; do | |
124 | + continue | |
125 | + done | |
111 | 126 | # ${service}.rc does the heavy lifting with the following trigger |
112 | - su root setprop ${property} ${service} | |
113 | - getprop ${property} | |
127 | + setprop ${property} ${service} | |
114 | 128 | # 20ms done, to permit process feedback check |
115 | 129 | sleep 1 |
130 | + getprop ${property#persist.} | |
116 | 131 | # also generate an error return code if not found running, bonus |
117 | 132 | ps -t | grep "${data##*/}.*${service%d}" |
118 | 133 | ;; |
@@ -120,19 +135,24 @@ case ${progname} in | ||
120 | 135 | if [ -n "${size}${buffer}" ]; then |
121 | 136 | echo "WARNING: Can not use --size or --buffer with ${progname%.*}.stop" >&2 |
122 | 137 | fi |
123 | - su root stop ${service} | |
124 | - su root setprop ${property} "" | |
125 | - if [ -n "`getprop ${property}.buffer`" ]; then | |
126 | - su root setprop ${property}.buffer "" | |
138 | + if [ "true" = "${clear}" ]; then | |
139 | + setprop ${property} "clear" | |
140 | + else | |
141 | + setprop ${property} "stop" | |
127 | 142 | fi |
128 | - if [ -n "`getprop ${property}.size`" ]; then | |
129 | - su root setprop ${property}.size "" | |
143 | + if [ -n "`getprop ${property#persist.}.buffer`" ]; then | |
144 | + setprop ${property}.buffer "" | |
145 | + # deal with trampoline for empty properties | |
146 | + setprop ${property#persist.}.buffer "" | |
130 | 147 | fi |
131 | - if [ "true" = "${clear}" ]; then | |
132 | - # 20ms done, guarantees content stop before rm | |
133 | - sleep 1 | |
134 | - su logd,misc rm -rf "${data}" | |
148 | + if [ -n "`getprop ${property#persist.}.size`" ]; then | |
149 | + setprop ${property}.size "" | |
150 | + # deal with trampoline for empty properties | |
151 | + setprop ${property#persist.}.size "" | |
135 | 152 | fi |
153 | + while [ "clear" = "`getprop ${property#persist.}`" ]; do | |
154 | + continue | |
155 | + done | |
136 | 156 | ;; |
137 | 157 | *) |
138 | 158 | echo "ERROR: Unexpected command ${0##*/} ${args}" >&2 |
@@ -28,6 +28,8 @@ | ||
28 | 28 | #include <log/logger.h> |
29 | 29 | #include <log/log_read.h> |
30 | 30 | |
31 | +#define BIG_BUFFER (5 * 1024) | |
32 | + | |
31 | 33 | // enhanced version of LOG_FAILURE_RETRY to add support for EAGAIN and |
32 | 34 | // non-syscall libs. Since we are only using this in the emergency of |
33 | 35 | // a signal to stuff a terminating code into the logs, we will spin rather |
@@ -52,7 +54,7 @@ TEST(logcat, buckets) { | ||
52 | 54 | "logcat -b radio -b events -b system -b main -d 2>/dev/null", |
53 | 55 | "r"))); |
54 | 56 | |
55 | - char buffer[5120]; | |
57 | + char buffer[BIG_BUFFER]; | |
56 | 58 | |
57 | 59 | int ids = 0; |
58 | 60 | int count = 0; |
@@ -100,7 +102,7 @@ TEST(logcat, year) { | ||
100 | 102 | "logcat -v long -v year -b all -t 3 2>/dev/null", |
101 | 103 | "r"))); |
102 | 104 | |
103 | - char buffer[5120]; | |
105 | + char buffer[BIG_BUFFER]; | |
104 | 106 | |
105 | 107 | int count = 0; |
106 | 108 |
@@ -163,7 +165,7 @@ TEST(logcat, tz) { | ||
163 | 165 | "logcat -v long -v America/Los_Angeles -b all -t 3 2>/dev/null", |
164 | 166 | "r"))); |
165 | 167 | |
166 | - char buffer[5120]; | |
168 | + char buffer[BIG_BUFFER]; | |
167 | 169 | |
168 | 170 | count = 0; |
169 | 171 |
@@ -187,7 +189,7 @@ TEST(logcat, ntz) { | ||
187 | 189 | "logcat -v long -v America/Los_Angeles -v zone -b all -t 3 2>/dev/null", |
188 | 190 | "r"))); |
189 | 191 | |
190 | - char buffer[5120]; | |
192 | + char buffer[BIG_BUFFER]; | |
191 | 193 | |
192 | 194 | int count = 0; |
193 | 195 |
@@ -207,7 +209,7 @@ void do_tail(int num) { | ||
207 | 209 | int count; |
208 | 210 | |
209 | 211 | do { |
210 | - char buffer[5120]; | |
212 | + char buffer[BIG_BUFFER]; | |
211 | 213 | |
212 | 214 | snprintf(buffer, sizeof(buffer), |
213 | 215 | "logcat -v long -b radio -b events -b system -b main -t %d 2>/dev/null", |
@@ -250,7 +252,7 @@ TEST(logcat, tail_time) { | ||
250 | 252 | |
251 | 253 | ASSERT_TRUE(NULL != (fp = popen("logcat -v long -b all -t 10 2>&1", "r"))); |
252 | 254 | |
253 | - char buffer[5120]; | |
255 | + char buffer[BIG_BUFFER]; | |
254 | 256 | char *last_timestamp = NULL; |
255 | 257 | char *first_timestamp = NULL; |
256 | 258 | int count = 0; |
@@ -313,7 +315,7 @@ TEST(logcat, End_to_End) { | ||
313 | 315 | "logcat -v brief -b events -t 100 2>/dev/null", |
314 | 316 | "r"))); |
315 | 317 | |
316 | - char buffer[5120]; | |
318 | + char buffer[BIG_BUFFER]; | |
317 | 319 | |
318 | 320 | int count = 0; |
319 | 321 |
@@ -337,15 +339,17 @@ TEST(logcat, End_to_End) { | ||
337 | 339 | ASSERT_EQ(1, count); |
338 | 340 | } |
339 | 341 | |
340 | -TEST(logcat, get_size) { | |
342 | +int get_groups(const char *cmd) { | |
341 | 343 | FILE *fp; |
342 | 344 | |
343 | 345 | // NB: crash log only available in user space |
344 | - ASSERT_TRUE(NULL != (fp = popen( | |
345 | - "logcat -v brief -b radio -b events -b system -b main -g 2>/dev/null", | |
346 | - "r"))); | |
346 | + EXPECT_TRUE(NULL != (fp = popen(cmd, "r"))); | |
347 | + | |
348 | + if (fp == NULL) { | |
349 | + return 0; | |
350 | + } | |
347 | 351 | |
348 | - char buffer[5120]; | |
352 | + char buffer[BIG_BUFFER]; | |
349 | 353 | |
350 | 354 | int count = 0; |
351 | 355 |
@@ -405,7 +409,23 @@ TEST(logcat, get_size) { | ||
405 | 409 | |
406 | 410 | pclose(fp); |
407 | 411 | |
408 | - ASSERT_EQ(4, count); | |
412 | + return count; | |
413 | +} | |
414 | + | |
415 | +TEST(logcat, get_size) { | |
416 | + ASSERT_EQ(4, get_groups( | |
417 | + "logcat -v brief -b radio -b events -b system -b main -g 2>/dev/null")); | |
418 | +} | |
419 | + | |
420 | +// duplicate test for get_size, but use comma-separated list of buffers | |
421 | +TEST(logcat, multiple_buffer) { | |
422 | + ASSERT_EQ(4, get_groups( | |
423 | + "logcat -v brief -b radio,events,system,main -g 2>/dev/null")); | |
424 | +} | |
425 | + | |
426 | +TEST(logcat, bad_buffer) { | |
427 | + ASSERT_EQ(0, get_groups( | |
428 | + "logcat -v brief -b radio,events,bogo,system,main -g 2>/dev/null")); | |
409 | 429 | } |
410 | 430 | |
411 | 431 | static void caught_blocking(int /*signum*/) |
@@ -434,7 +454,7 @@ TEST(logcat, blocking) { | ||
434 | 454 | " logcat -v brief -b events 2>&1", |
435 | 455 | "r"))); |
436 | 456 | |
437 | - char buffer[5120]; | |
457 | + char buffer[BIG_BUFFER]; | |
438 | 458 | |
439 | 459 | int count = 0; |
440 | 460 |
@@ -503,7 +523,7 @@ TEST(logcat, blocking_tail) { | ||
503 | 523 | " logcat -v brief -b events -T 5 2>&1", |
504 | 524 | "r"))); |
505 | 525 | |
506 | - char buffer[5120]; | |
526 | + char buffer[BIG_BUFFER]; | |
507 | 527 | |
508 | 528 | int count = 0; |
509 | 529 |
@@ -566,7 +586,7 @@ TEST(logcat, logrotate) { | ||
566 | 586 | FILE *fp; |
567 | 587 | EXPECT_TRUE(NULL != (fp = popen(command, "r"))); |
568 | 588 | if (fp) { |
569 | - char buffer[5120]; | |
589 | + char buffer[BIG_BUFFER]; | |
570 | 590 | int count = 0; |
571 | 591 | |
572 | 592 | while (fgets(buffer, sizeof(buffer), fp)) { |
@@ -609,7 +629,7 @@ TEST(logcat, logrotate_suffix) { | ||
609 | 629 | |
610 | 630 | FILE *fp; |
611 | 631 | EXPECT_TRUE(NULL != (fp = popen(command, "r"))); |
612 | - char buffer[5120]; | |
632 | + char buffer[BIG_BUFFER]; | |
613 | 633 | int log_file_count = 0; |
614 | 634 | |
615 | 635 | while (fgets(buffer, sizeof(buffer), fp)) { |
@@ -751,6 +771,82 @@ TEST(logcat, logrotate_continue) { | ||
751 | 771 | EXPECT_FALSE(system(command)); |
752 | 772 | } |
753 | 773 | |
774 | +TEST(logcat, logrotate_clear) { | |
775 | + static const char tmp_out_dir_form[] = "/data/local/tmp/logcat.logrotate.XXXXXX"; | |
776 | + char tmp_out_dir[sizeof(tmp_out_dir_form)]; | |
777 | + ASSERT_TRUE(NULL != mkdtemp(strcpy(tmp_out_dir, tmp_out_dir_form))); | |
778 | + | |
779 | + static const char log_filename[] = "log.txt"; | |
780 | + static const unsigned num_val = 32; | |
781 | + static const char logcat_cmd[] = "logcat -b all -d -f %s/%s -n %d -r 1"; | |
782 | + static const char clear_cmd[] = " -c"; | |
783 | + static const char cleanup_cmd[] = "rm -rf %s"; | |
784 | + char command[sizeof(tmp_out_dir) + sizeof(logcat_cmd) + sizeof(log_filename) + sizeof(clear_cmd) + 32]; | |
785 | + | |
786 | + // Run command with all data | |
787 | + { | |
788 | + snprintf(command, sizeof(command) - sizeof(clear_cmd), | |
789 | + logcat_cmd, tmp_out_dir, log_filename, num_val); | |
790 | + | |
791 | + int ret; | |
792 | + EXPECT_FALSE((ret = system(command))); | |
793 | + if (ret) { | |
794 | + snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir); | |
795 | + EXPECT_FALSE(system(command)); | |
796 | + return; | |
797 | + } | |
798 | + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir); | |
799 | + EXPECT_NE(nullptr, dir); | |
800 | + if (!dir) { | |
801 | + snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir); | |
802 | + EXPECT_FALSE(system(command)); | |
803 | + return; | |
804 | + } | |
805 | + struct dirent *entry; | |
806 | + unsigned count = 0; | |
807 | + while ((entry = readdir(dir.get()))) { | |
808 | + if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) { | |
809 | + continue; | |
810 | + } | |
811 | + ++count; | |
812 | + } | |
813 | + EXPECT_EQ(count, num_val + 1); | |
814 | + } | |
815 | + | |
816 | + { | |
817 | + // Now with -c option tacked onto the end | |
818 | + strcat(command, clear_cmd); | |
819 | + | |
820 | + int ret; | |
821 | + EXPECT_FALSE((ret = system(command))); | |
822 | + if (ret) { | |
823 | + snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir); | |
824 | + EXPECT_FALSE(system(command)); | |
825 | + return; | |
826 | + } | |
827 | + std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(tmp_out_dir), closedir); | |
828 | + EXPECT_NE(nullptr, dir); | |
829 | + if (!dir) { | |
830 | + snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir); | |
831 | + EXPECT_FALSE(system(command)); | |
832 | + return; | |
833 | + } | |
834 | + struct dirent *entry; | |
835 | + unsigned count = 0; | |
836 | + while ((entry = readdir(dir.get()))) { | |
837 | + if (strncmp(entry->d_name, log_filename, sizeof(log_filename) - 1)) { | |
838 | + continue; | |
839 | + } | |
840 | + fprintf(stderr, "Found %s/%s!!!\n", tmp_out_dir, entry->d_name); | |
841 | + ++count; | |
842 | + } | |
843 | + EXPECT_EQ(count, 0U); | |
844 | + } | |
845 | + | |
846 | + snprintf(command, sizeof(command), cleanup_cmd, tmp_out_dir); | |
847 | + EXPECT_FALSE(system(command)); | |
848 | +} | |
849 | + | |
754 | 850 | TEST(logcat, logrotate_nodir) { |
755 | 851 | // expect logcat to error out on writing content and exit(1) for nodir |
756 | 852 | EXPECT_EQ(W_EXITCODE(1, 0), |
@@ -783,7 +879,7 @@ TEST(logcat, blocking_clear) { | ||
783 | 879 | " logcat -v brief -b events 2>&1", |
784 | 880 | "r"))); |
785 | 881 | |
786 | - char buffer[5120]; | |
882 | + char buffer[BIG_BUFFER]; | |
787 | 883 | |
788 | 884 | int count = 0; |
789 | 885 |
@@ -844,7 +940,7 @@ static bool get_white_black(char **list) { | ||
844 | 940 | return false; |
845 | 941 | } |
846 | 942 | |
847 | - char buffer[5120]; | |
943 | + char buffer[BIG_BUFFER]; | |
848 | 944 | |
849 | 945 | while (fgets(buffer, sizeof(buffer), fp)) { |
850 | 946 | char *hold = *list; |
@@ -873,7 +969,7 @@ static bool get_white_black(char **list) { | ||
873 | 969 | static bool set_white_black(const char *list) { |
874 | 970 | FILE *fp; |
875 | 971 | |
876 | - char buffer[5120]; | |
972 | + char buffer[BIG_BUFFER]; | |
877 | 973 | |
878 | 974 | snprintf(buffer, sizeof(buffer), "logcat -P '%s' 2>&1", list ? list : ""); |
879 | 975 | fp = popen(buffer, "r"); |
@@ -935,7 +1031,7 @@ TEST(logcat, regex) { | ||
935 | 1031 | FILE *fp; |
936 | 1032 | int count = 0; |
937 | 1033 | |
938 | - char buffer[5120]; | |
1034 | + char buffer[BIG_BUFFER]; | |
939 | 1035 | |
940 | 1036 | snprintf(buffer, sizeof(buffer), "logcat --pid %d -d -e logcat_test_a+b", getpid()); |
941 | 1037 |
@@ -968,7 +1064,7 @@ TEST(logcat, maxcount) { | ||
968 | 1064 | FILE *fp; |
969 | 1065 | int count = 0; |
970 | 1066 | |
971 | - char buffer[5120]; | |
1067 | + char buffer[BIG_BUFFER]; | |
972 | 1068 | |
973 | 1069 | snprintf(buffer, sizeof(buffer), "logcat --pid %d -d --max-count 3", getpid()); |
974 | 1070 |
@@ -1,4 +1,4 @@ | ||
1 | -The properties that logd responds to are: | |
1 | +The properties that logd and friends react to are: | |
2 | 2 | |
3 | 3 | name type default description |
4 | 4 | ro.logd.auditd bool true Enable selinux audit daemon |
@@ -10,8 +10,16 @@ ro.logd.kernel bool+ svelte+ Enable klogd daemon | ||
10 | 10 | ro.logd.statistics bool+ svelte+ Enable logcat -S statistics. |
11 | 11 | ro.build.type string if user, logd.statistics & |
12 | 12 | ro.logd.kernel default false. |
13 | +logd.logpersistd.enable bool auto Safe to start logpersist daemon service | |
14 | +logd.logpersistd string persist Enable logpersist daemon, "logcatd" | |
15 | + turns on logcat -f in logd context. | |
16 | + Responds to logcatd, clear and stop. | |
17 | +logd.logpersistd.buffer persist logpersistd buffers to collect | |
18 | +logd.logpersistd.size persist logpersistd size in MB | |
13 | 19 | persist.logd.logpersistd string Enable logpersist daemon, "logcatd" |
14 | - turns on logcat -f in logd context | |
20 | + turns on logcat -f in logd context. | |
21 | +persist.logd.logpersistd.buffer all logpersistd buffers to collect | |
22 | +persist.logd.logpersistd.size 256 logpersistd size in MB | |
15 | 23 | persist.logd.size number ro Global default size of the buffer for |
16 | 24 | all log ids at initial startup, at |
17 | 25 | runtime use: logcat -b all -G <value> |
@@ -45,6 +53,7 @@ log.tag.<tag> string persist The <tag> specific logging level. | ||
45 | 53 | persist.log.tag.<tag> string build default for log.tag.<tag> |
46 | 54 | |
47 | 55 | NB: |
56 | +- auto - managed by /init | |
48 | 57 | - bool+ - "true", "false" and comma separated list of "eng" (forced false if |
49 | 58 | ro.build.type is "user") or "svelte" (forced false if ro.config.low_ram is |
50 | 59 | true). |