blob: ceb6ade98a547b3b6ef2c8cf92bbaa4534735722 [file] [log] [blame]
Zhengyin Qian2b28ca22015-06-18 21:37:41 -07001/*
2 * Copyright (c) 2015, The Android Open Source Project
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google, Inc. nor the names of its contributors
15 * may be used to endorse or promote products derived from this
16 * software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <binder/IBinder.h>
33#include <binder/IServiceManager.h>
34#include <binder/Parcel.h>
35
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070036#include <cutils/properties.h>
37#include <signal.h>
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070038#include <stdio.h>
39#include <stdlib.h>
40#include <string.h>
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +020041#include <ctime>
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070042
43#include <sys/resource.h>
44#include <sys/stat.h>
45#include <sys/time.h>
46#include <sys/types.h>
47#include <unistd.h>
48
49#include <utils/Log.h>
50#include <utils/String8.h>
51#include <utils/Trace.h>
52#include <zlib.h>
53
54using namespace android;
55
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070056#ifdef LOG_TAG
57#undef LOG_TAG
58#endif
59
60#define LOG_TAG "anrdaemon"
61
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +020062static const int check_period = 1; // in sec
63static const int tracing_check_period = 500000; // in micro sec
64static const int cpu_stat_entries = 7; // number of cpu stat entries
Zhengyin Qian95335ba2016-04-26 15:14:27 -070065static const int min_buffer_size = 16;
66static const int max_buffer_size = 2048;
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +020067static const char* min_buffer_size_str = "16";
68static const char* max_buffer_size_str = "2048";
Zhengyin Qiand93aa412016-06-21 14:05:44 -070069static const int time_buf_size = 20;
70static const int path_buf_size = 60;
Zhengyin Qian95335ba2016-04-26 15:14:27 -070071
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070072typedef struct cpu_stat {
73 unsigned long utime, ntime, stime, itime;
74 unsigned long iowtime, irqtime, sirqtime, steal;
75 unsigned long total;
76} cpu_stat_t;
77
Zhengyin Qianfaf487d2016-04-26 11:57:16 -070078/*
79 * Logging on/off threshold.
80 * Uint: 0.01%; default to 99.90% cpu.
81 */
82static int idle_threshold = 10;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070083
84static bool quit = false;
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +020085static bool suspend = false;
Zhengyin Qianb4037792016-09-07 15:57:23 -070086static bool dump_requested = false;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070087static bool err = false;
88static char err_msg[100];
89static bool tracing = false;
90
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +020091static const char* buf_size_kb = "2048";
92static const char* apps = "";
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070093static uint64_t tag = 0;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070094
95static cpu_stat_t new_cpu;
96static cpu_stat_t old_cpu;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -070097
98/* Log certain kernel activity when enabled */
99static bool log_sched = false;
100static bool log_stack = false;
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200101static bool log_irq = false;
102static bool log_sync = false;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700103static bool log_workq = false;
104
105/* Paths for debugfs controls*/
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200106static const char* dfs_trace_output_path = "/d/tracing/trace";
107static const char* dfs_irq_path = "/d/tracing/events/irq/enable";
108static const char* dfs_sync_path = "/d/tracing/events/sync/enable";
109static const char* dfs_workq_path = "/d/tracing/events/workqueue/enable";
110static const char* dfs_stack_path = "/d/tracing/options/stacktrace";
111static const char* dfs_sched_switch_path = "/d/tracing/events/sched/sched_switch/enable";
112static const char* dfs_sched_wakeup_path = "/d/tracing/events/sched/sched_wakeup/enable";
113static const char* dfs_control_path = "/d/tracing/tracing_on";
114static const char* dfs_buffer_size_path = "/d/tracing/buffer_size_kb";
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700115static const char* dfs_tags_property = "debug.atrace.tags.enableflags";
116static const char* dfs_apps_property = "debug.atrace.app_cmdlines";
117
118/*
119 * Read accumulated cpu data from /proc/stat
120 */
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200121static void get_cpu_stat(cpu_stat_t* cpu) {
122 FILE* fp = NULL;
123 const char* params = "cpu %lu %lu %lu %lu %lu %lu %lu %*d %*d %*d\n";
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700124
125 if ((fp = fopen("/proc/stat", "r")) == NULL) {
126 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700127 snprintf(err_msg, sizeof(err_msg), "can't read from /proc/stat with errno %d", errno);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700128 } else {
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200129 if (fscanf(fp, params, &cpu->utime, &cpu->ntime, &cpu->stime, &cpu->itime, &cpu->iowtime,
130 &cpu->irqtime, &cpu->sirqtime) != cpu_stat_entries) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700131 /*
132 * If failed in getting status, new_cpu won't be updated and
133 * is_heavy_loaded() will return false.
134 */
135 ALOGE("Error in getting cpu status. Skipping this check.");
Greg Kaiser2489b682016-08-11 11:40:44 -0700136 fclose(fp);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700137 return;
138 }
139
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200140 cpu->total = cpu->utime + cpu->ntime + cpu->stime + cpu->itime + cpu->iowtime +
141 cpu->irqtime + cpu->sirqtime;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700142
143 fclose(fp);
144 }
145}
146
147/*
148 * Calculate cpu usage in the past interval.
Zhengyin Qianfaf487d2016-04-26 11:57:16 -0700149 * If tracing is on, increase the idle threshold by 1.00% so that we do not
Connor Watts6e423812016-06-03 10:57:39 -0700150 * turn on and off tracing frequently when the cpu load is right close to
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700151 * threshold.
152 */
153static bool is_heavy_load(void) {
154 unsigned long diff_idle, diff_total;
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200155 int threshold = idle_threshold + (tracing ? 100 : 0);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700156 get_cpu_stat(&new_cpu);
157 diff_idle = new_cpu.itime - old_cpu.itime;
158 diff_total = new_cpu.total - old_cpu.total;
159 old_cpu = new_cpu;
Zhengyin Qianfaf487d2016-04-26 11:57:16 -0700160 return (diff_idle * 10000 < diff_total * threshold);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700161}
162
163/*
164 * Force the userland processes to refresh their property for logging.
165 */
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700166static void dfs_poke_binder(void) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700167 sp<IServiceManager> sm = defaultServiceManager();
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700168 Vector<String16> services = sm->listServices();
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700169 for (size_t i = 0; i < services.size(); i++) {
170 sp<IBinder> obj = sm->checkService(services[i]);
171 if (obj != NULL) {
172 Parcel data;
173 obj->transact(IBinder::SYSPROPS_TRANSACTION, data, NULL, 0);
174 }
175 }
176}
177
178/*
179 * Enable/disable a debugfs property by writing 0/1 to its path.
180 */
181static int dfs_enable(bool enable, const char* path) {
182 int fd = open(path, O_WRONLY);
183 if (fd == -1) {
184 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700185 snprintf(err_msg, sizeof(err_msg), "Can't open %s. Error: %d", path, errno);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700186 return -1;
187 }
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200188 const char* control = (enable ? "1" : "0");
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700189 ssize_t len = strlen(control);
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200190 int max_try = 10; // Fail if write was interrupted for 10 times
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700191 while (write(fd, control, len) != len) {
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700192 if (errno == EINTR && max_try-- > 0) {
193 usleep(100);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700194 continue;
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700195 }
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700196
197 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700198 snprintf(err_msg, sizeof(err_msg), "Error %d in writing to %s.", errno, path);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700199 }
200 close(fd);
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200201 return (err ? -1 : 0);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700202}
203
204/*
205 * Set the userland tracing properties.
206 */
207static void dfs_set_property(uint64_t mtag, const char* mapp, bool enable) {
208 char buf[64];
Wei Wangfc665a12016-10-12 14:35:51 -0700209 snprintf(buf, sizeof(buf), "%#" PRIx64, mtag);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700210 if (property_set(dfs_tags_property, buf) < 0) {
211 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700212 snprintf(err_msg, sizeof(err_msg), "Failed to set debug tags system properties.");
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700213 }
214
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200215 if (strlen(mapp) > 0 && property_set(dfs_apps_property, mapp) < 0) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700216 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700217 snprintf(err_msg, sizeof(err_msg), "Failed to set debug applications.");
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700218 }
219
220 if (log_sched) {
221 dfs_enable(enable, dfs_sched_switch_path);
222 dfs_enable(enable, dfs_sched_wakeup_path);
223 }
224 if (log_stack) {
225 dfs_enable(enable, dfs_stack_path);
226 }
227 if (log_irq) {
228 dfs_enable(enable, dfs_irq_path);
229 }
230 if (log_sync) {
231 dfs_enable(enable, dfs_sync_path);
232 }
233 if (log_workq) {
234 dfs_enable(enable, dfs_workq_path);
235 }
236}
237
238/*
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700239 * Dump the log in a compressed format for systrace to visualize.
Zhengyin Qianb4037792016-09-07 15:57:23 -0700240 * Create a dump file "dump_of_anrdaemon.<current_time>" under /data/misc/anrd
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700241 */
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200242static void dump_trace() {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700243 time_t now = time(0);
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200244 struct tm tstruct;
Zhengyin Qiand93aa412016-06-21 14:05:44 -0700245 char time_buf[time_buf_size];
246 char path_buf[path_buf_size];
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700247 const char* header = " done\nTRACE:\n";
248 ssize_t header_len = strlen(header);
Zhengyin Qianb4037792016-09-07 15:57:23 -0700249
250 ALOGI("Started to dump ANRdaemon trace.");
251
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700252 tstruct = *localtime(&now);
Zhengyin Qiand93aa412016-06-21 14:05:44 -0700253 strftime(time_buf, time_buf_size, "%Y-%m-%d.%X", &tstruct);
254 snprintf(path_buf, path_buf_size, "/data/misc/anrd/dump_of_anrdaemon.%s", time_buf);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700255 int output_fd = creat(path_buf, S_IRWXU);
256 if (output_fd == -1) {
257 ALOGE("Failed to create %s. Dump aborted.", path_buf);
258 return;
259 }
260
261 if (write(output_fd, header, strlen(header)) != header_len) {
262 ALOGE("Failed to write the header.");
263 close(output_fd);
264 return;
265 }
266
267 int trace_fd = open(dfs_trace_output_path, O_RDWR);
268 if (trace_fd == -1) {
269 ALOGE("Failed to open %s. Dump aborted.", dfs_trace_output_path);
270 close(output_fd);
271 return;
272 }
273
274 z_stream zs;
275 uint8_t *in, *out;
276 int result, flush;
277
278 memset(&zs, 0, sizeof(zs));
279 result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
280 if (result != Z_OK) {
281 ALOGE("error initializing zlib: %d\n", result);
282 close(trace_fd);
283 close(output_fd);
284 return;
285 }
286
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200287 const size_t bufSize = 64 * 1024;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700288 in = (uint8_t*)malloc(bufSize);
289 out = (uint8_t*)malloc(bufSize);
290 flush = Z_NO_FLUSH;
291
292 zs.next_out = out;
293 zs.avail_out = bufSize;
294
295 do {
296 if (zs.avail_in == 0) {
297 result = read(trace_fd, in, bufSize);
298 if (result < 0) {
299 ALOGE("error reading trace: %s", strerror(errno));
300 result = Z_STREAM_END;
301 break;
302 } else if (result == 0) {
303 flush = Z_FINISH;
304 } else {
305 zs.next_in = in;
306 zs.avail_in = result;
307 }
308 }
309
310 if (zs.avail_out == 0) {
311 result = write(output_fd, out, bufSize);
312 if ((size_t)result < bufSize) {
313 ALOGE("error writing deflated trace: %s", strerror(errno));
314 result = Z_STREAM_END;
315 zs.avail_out = bufSize;
316 break;
317 }
318 zs.next_out = out;
319 zs.avail_out = bufSize;
320 }
321
322 } while ((result = deflate(&zs, flush)) == Z_OK);
323
324 if (result != Z_STREAM_END) {
325 ALOGE("error deflating trace: %s\n", zs.msg);
326 }
327
328 if (zs.avail_out < bufSize) {
329 size_t bytes = bufSize - zs.avail_out;
330 result = write(output_fd, out, bytes);
331 if ((size_t)result < bytes) {
332 ALOGE("error writing deflated trace: %s", strerror(errno));
333 }
334 }
335
336 result = deflateEnd(&zs);
337 if (result != Z_OK) {
338 ALOGE("error cleaning up zlib: %d\n", result);
339 }
340
341 free(in);
342 free(out);
343
344 close(trace_fd);
345 close(output_fd);
346
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700347 ALOGI("Finished dump. Output file stored at: %s", path_buf);
348}
349
Zhengyin Qianb4037792016-09-07 15:57:23 -0700350/*
351 * Start logging when cpu usage is high. Meanwhile, moniter the cpu usage and
352 * stop logging when it drops down.
353 */
354static void start_tracing(void) {
355 ALOGD("High cpu usage, start logging.");
356
357 if (dfs_enable(true, dfs_control_path) != 0) {
358 ALOGE("Failed to start tracing.");
359 return;
360 }
361 tracing = true;
362
363 /* Stop logging when cpu usage drops or the daemon is suspended.*/
364 do {
365 usleep(tracing_check_period);
366 } while (!suspend && !dump_requested && is_heavy_load());
367
368 if (dfs_enable(false, dfs_control_path) != 0) {
369 ALOGE("Failed to stop tracing.");
370 err = true;
371 return;
372 }
373 tracing = false;
374
375 if (suspend) {
376 ALOGI("trace stopped due to suspend. Send SIGCONT to resume.");
377 } else if (dump_requested) {
378 ALOGI("trace stopped due to dump request.");
379 dump_trace();
380 dump_requested = false;
381 } else {
382 ALOGD("Usage back to low, stop logging.");
383 }
384}
385
386/*
387 * Set the tracing log buffer size.
388 * Note the actual buffer size will be buf_size_kb * number of cores.
389 */
390static int set_tracing_buffer_size(void) {
391 int fd = open(dfs_buffer_size_path, O_WRONLY);
392 if (fd == -1) {
393 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700394 snprintf(err_msg, sizeof(err_msg), "Can't open atrace buffer size file under /d/tracing.");
Zhengyin Qianb4037792016-09-07 15:57:23 -0700395 return -1;
396 }
397 ssize_t len = strlen(buf_size_kb);
398 if (write(fd, buf_size_kb, len) != len) {
399 err = true;
Wei Wangfc665a12016-10-12 14:35:51 -0700400 snprintf(err_msg, sizeof(err_msg), "Error in writing to atrace buffer size file.");
Zhengyin Qianb4037792016-09-07 15:57:23 -0700401 }
402 close(fd);
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200403 return (err ? -1 : 0);
Zhengyin Qianb4037792016-09-07 15:57:23 -0700404}
405
406/*
407 * Main loop to moniter the cpu usage and decided whether to start logging.
408 */
409static void start(void) {
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200410 if ((set_tracing_buffer_size()) != 0) return;
Zhengyin Qianb4037792016-09-07 15:57:23 -0700411
412 dfs_set_property(tag, apps, true);
413 dfs_poke_binder();
414
415 get_cpu_stat(&old_cpu);
416 sleep(check_period);
417
418 while (!quit && !err) {
419 if (!suspend && is_heavy_load()) {
420 /*
421 * Increase process priority to make sure we can stop logging when
422 * necessary and do not overwrite the buffer
423 */
424 setpriority(PRIO_PROCESS, 0, -20);
425 start_tracing();
426 setpriority(PRIO_PROCESS, 0, 0);
427 }
428 sleep(check_period);
429 }
430 return;
431}
432
433/*
434 * If trace is not running, dump trace right away.
435 * If trace is running, request to dump trace.
436 */
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200437static void request_dump_trace() {
Zhengyin Qianb4037792016-09-07 15:57:23 -0700438 if (!tracing) {
439 dump_trace();
440 } else if (!dump_requested) {
441 dump_requested = true;
442 }
443}
444
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200445static void handle_signal(int signo) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700446 switch (signo) {
447 case SIGQUIT:
448 suspend = true;
449 quit = true;
450 break;
451 case SIGSTOP:
452 suspend = true;
453 break;
454 case SIGCONT:
455 suspend = false;
456 break;
457 case SIGUSR1:
Zhengyin Qianb4037792016-09-07 15:57:23 -0700458 request_dump_trace();
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700459 }
460}
461
462/*
463 * Set the signal handler:
464 * SIGQUIT: Reset debugfs and tracing property and terminate the daemon.
465 * SIGSTOP: Stop logging and suspend the daemon.
466 * SIGCONT: Resume the daemon as normal.
467 * SIGUSR1: Dump the logging to a compressed format for systrace to visualize.
468 */
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200469static void register_sighandler(void) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700470 struct sigaction sa;
471 sigset_t block_mask;
472
473 sigemptyset(&block_mask);
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200474 sigaddset(&block_mask, SIGQUIT);
475 sigaddset(&block_mask, SIGSTOP);
476 sigaddset(&block_mask, SIGCONT);
477 sigaddset(&block_mask, SIGUSR1);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700478
479 sa.sa_flags = 0;
480 sa.sa_mask = block_mask;
481 sa.sa_handler = handle_signal;
482 sigaction(SIGQUIT, &sa, NULL);
483 sigaction(SIGSTOP, &sa, NULL);
484 sigaction(SIGCONT, &sa, NULL);
485 sigaction(SIGUSR1, &sa, NULL);
486}
487
488static void show_help(void) {
hongzhu wang99c043e2021-11-29 01:20:21 +0000489 fprintf(stderr, "usage: anrd [options] [categoris...]\n");
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200490 fprintf(stdout,
491 "Options includes:\n"
492 " -a appname enable app-level tracing for a comma "
493 "separated list of cmdlines\n"
494 " -t N cpu threshold for logging to start "
495 "(uint = 0.01%%, min = 5000, max = 9999, default = 9990)\n"
496 " -s N use a trace buffer size of N KB "
497 "default to 2048KB\n"
498 " -h show helps\n");
499 fprintf(stdout,
500 "Categoris includes:\n"
501 " am - activity manager\n"
502 " sm - sync manager\n"
503 " input - input\n"
504 " dalvik - dalvik VM\n"
505 " audio - Audio\n"
506 " gfx - Graphics\n"
507 " rs - RenderScript\n"
508 " hal - Hardware Modules\n"
509 " irq - kernel irq events\n"
510 " sched - kernel scheduler activity\n"
511 " stack - kernel stack\n"
512 " sync - kernel sync activity\n"
513 " workq - kernel work queues\n");
514 fprintf(stdout,
515 "Control includes:\n"
516 " SIGQUIT: terminate the process\n"
517 " SIGSTOP: suspend all function of the daemon\n"
518 " SIGCONT: resume the normal function\n"
519 " SIGUSR1: dump the current logging in a compressed form\n");
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700520 exit(0);
521}
522
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200523static int get_options(int argc, char* argv[]) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700524 int opt = 0;
525 int threshold;
526 while ((opt = getopt(argc, argv, "a:s:t:h")) >= 0) {
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200527 switch (opt) {
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700528 case 'a':
529 apps = optarg;
530 break;
531 case 's':
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700532 if (atoi(optarg) > max_buffer_size)
533 buf_size_kb = max_buffer_size_str;
534 else if (atoi(optarg) < min_buffer_size)
535 buf_size_kb = min_buffer_size_str;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700536 else
537 buf_size_kb = optarg;
538 break;
539 case 't':
540 threshold = atoi(optarg);
Zhengyin Qianfaf487d2016-04-26 11:57:16 -0700541 if (threshold > 9999 || threshold < 5000) {
542 fprintf(stderr, "logging threshold should be 5000-9999\n");
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700543 return 1;
544 }
Zhengyin Qianfaf487d2016-04-26 11:57:16 -0700545 idle_threshold = 10000 - threshold;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700546 break;
547 case 'h':
548 show_help();
549 break;
550 default:
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200551 fprintf(stderr,
552 "Error in getting options.\n"
553 "run \"%s -h\" for usage.\n",
554 argv[0]);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700555 return 1;
556 }
557 }
558
559 for (int i = optind; i < argc; i++) {
560 if (strcmp(argv[i], "am") == 0) {
561 tag |= ATRACE_TAG_ACTIVITY_MANAGER;
562 } else if (strcmp(argv[i], "input") == 0) {
563 tag |= ATRACE_TAG_INPUT;
564 } else if (strcmp(argv[i], "sm") == 0) {
565 tag |= ATRACE_TAG_SYNC_MANAGER;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700566 } else if (strcmp(argv[i], "dalvik") == 0) {
567 tag |= ATRACE_TAG_DALVIK;
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700568 } else if (strcmp(argv[i], "gfx") == 0) {
569 tag |= ATRACE_TAG_GRAPHICS;
570 } else if (strcmp(argv[i], "audio") == 0) {
571 tag |= ATRACE_TAG_AUDIO;
572 } else if (strcmp(argv[i], "hal") == 0) {
573 tag |= ATRACE_TAG_HAL;
574 } else if (strcmp(argv[i], "rs") == 0) {
575 tag |= ATRACE_TAG_RS;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700576 } else if (strcmp(argv[i], "sched") == 0) {
577 log_sched = true;
578 } else if (strcmp(argv[i], "stack") == 0) {
579 log_stack = true;
580 } else if (strcmp(argv[i], "workq") == 0) {
581 log_workq = true;
582 } else if (strcmp(argv[i], "irq") == 0) {
583 log_irq = true;
584 } else if (strcmp(argv[i], "sync") == 0) {
585 log_sync = true;
586 } else {
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200587 fprintf(stderr,
588 "invalid category: %s\n"
589 "run \"%s -h\" for usage.\n",
590 argv[i], argv[0]);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700591 return 1;
592 }
593 }
594
Zhengyin Qian95335ba2016-04-26 15:14:27 -0700595 /* If nothing is enabled, don't run */
596 if (!tag && !log_sched && !log_stack && !log_workq && !log_irq && !log_sync) {
597 ALOGE("Specify at least one category to trace.");
598 return 1;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700599 }
600
601 return 0;
602}
603
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200604int main(int argc, char* argv[]) {
605 if (get_options(argc, argv) != 0) return 1;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700606
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200607 if (daemon(0, 0) != 0) return 1;
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700608
609 register_sighandler();
610
611 /* Clear any the trace log file by overwrite it with a new file */
612 int fd = creat(dfs_trace_output_path, 0);
613 if (fd == -1) {
614 ALOGE("Faield to open and cleaup previous log");
615 return 1;
616 }
617 close(fd);
618
619 ALOGI("ANRdaemon starting");
620 start();
621
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200622 if (err) ALOGE("ANRdaemon stopped due to Error: %s", err_msg);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700623
624 ALOGI("ANRdaemon terminated.");
625
Thiébaud Weksteen3d7bd942020-10-23 16:49:30 +0200626 return (err ? 1 : 0);
Zhengyin Qian2b28ca22015-06-18 21:37:41 -0700627}