enum { MAX_SYS_FILES = 8 };
const char* k_traceTagsProperty = "debug.atrace.tags.enableflags";
+const char* k_traceAppCmdlineProperty = "debug.atrace.app_cmdlines";
typedef enum { OPT, REQ } requiredness ;
{ "video", "Video", ATRACE_TAG_VIDEO, { } },
{ "camera", "Camera", ATRACE_TAG_CAMERA, { } },
{ "hal", "Hardware Modules", ATRACE_TAG_HAL, { } },
+ { "res", "Resource Loading", ATRACE_TAG_RESOURCES, { } },
+ { "dalvik", "Dalvik VM", ATRACE_TAG_DALVIK, { } },
{ "sched", "CPU Scheduling", 0, {
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" },
{ REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" },
static bool g_nohup = false;
static int g_initialSleepSecs = 0;
static const char* g_kernelTraceFuncs = NULL;
+static const char* g_debugAppCmdLine = "";
/* Global state */
static bool g_traceAborted = false;
// Truncate a file.
static bool truncateFile(const char* path)
{
- int err = truncate(path, 0);
- if (err != 0) {
+ // This uses creat rather than truncate because some of the debug kernel
+ // device nodes (e.g. k_ftraceFilterPath) currently aren't changed by
+ // calls to truncate, but they are cleared by calls to creat.
+ int traceFD = creat(path, 0);
+ if (traceFD == -1) {
fprintf(stderr, "error truncating %s: %s (%d)\n", path,
- strerror(errno), errno);
+ strerror(errno), errno);
return false;
}
+ close(traceFD);
+
return true;
}
fprintf(stderr, "error setting trace tags system property\n");
return false;
}
- return pokeBinderServices();
+ return true;
+}
+
+// Set the system property that indicates which apps should perform
+// application-level tracing.
+static bool setAppCmdlineProperty(const char* cmdline)
+{
+ if (property_set(k_traceAppCmdlineProperty, cmdline) < 0) {
+ fprintf(stderr, "error setting trace app system property\n");
+ return false;
+ }
+ return true;
}
// Disable all /sys/ enable files.
if (funcs == NULL || funcs[0] == '\0') {
// Disable kernel function tracing.
- ok &= writeStr(k_currentTracerPath, "nop");
- if (fileExists(k_ftraceFilterPath)) {
+ if (fileIsWritable(k_currentTracerPath)) {
+ ok &= writeStr(k_currentTracerPath, "nop");
+ }
+ if (fileIsWritable(k_ftraceFilterPath)) {
ok &= truncateFile(k_ftraceFilterPath);
}
} else {
}
}
ok &= setTagsProperty(tags);
+ ok &= setAppCmdlineProperty(g_debugAppCmdLine);
+ ok &= pokeBinderServices();
// Disable all the sysfs enables. This is done as a separate loop from
// the enables to allow the same enable to exist in multiple categories.
// Disable all tracing that we're able to.
disableKernelTraceEvents();
- // Disable all the trace tags.
+ // Reset the system properties.
setTagsProperty(0);
+ setAppCmdlineProperty("");
+ pokeBinderServices();
// Set the options back to their defaults.
setTraceOverwriteEnable(true);
{
fprintf(stderr, "usage: %s [options] [categories...]\n", cmd);
fprintf(stderr, "options include:\n"
+ " -a appname enable app-level tracing for a comma "
+ "separated list of cmdlines\n"
" -b N use a trace buffer size of N KB\n"
" -c trace into a circular buffer\n"
" -k fname,... trace the listed kernel functions\n"
{ 0, 0, 0, 0 }
};
- ret = getopt_long(argc, argv, "b:ck:ns:t:z",
+ ret = getopt_long(argc, argv, "a:b:ck:ns:t:z",
long_options, &option_index);
if (ret < 0) {
}
switch(ret) {
+ case 'a':
+ g_debugAppCmdLine = optarg;
+ break;
+
case 'b':
g_traceBufferSizeKB = atoi(optarg);
break;
case 'k':
g_kernelTraceFuncs = optarg;
- break;
+ break;
case 'n':
g_nohup = true;
- break;
+ break;
case 's':
g_initialSleepSecs = atoi(optarg);
listSupportedCategories();
exit(0);
}
- break;
+ break;
default:
fprintf(stderr, "\n");