From 774f9299912cdf9f2a6b3805bb557e30bafbad05 Mon Sep 17 00:00:00 2001 From: Jamie Gennis Date: Mon, 25 Feb 2013 18:15:40 -0800 Subject: [PATCH] libcutils: add support for app tracing This change adds support for tracing using the ATRACE_TAG_APP tag. This tag is enabled only for processes in which the /proc//cmdline value appears in the comma-separated list of such values in the debug.atrace.app_cmdlines system property. It is also only enabled if either the ro.debuggable system property is set to 1 or the application has declared itself debuggable in its manifest, which gets reported to libcutils by the framework. Change-Id: Ic94ba55f4e70a9cf994056acbf151e523428b65d --- include/cutils/trace.h | 12 +++++- libcutils/trace.c | 90 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/include/cutils/trace.h b/include/cutils/trace.h index ad65dfba4..55aabdde7 100644 --- a/include/cutils/trace.h +++ b/include/cutils/trace.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -62,7 +63,8 @@ __BEGIN_DECLS #define ATRACE_TAG_VIDEO (1<<9) #define ATRACE_TAG_CAMERA (1<<10) #define ATRACE_TAG_HAL (1<<11) -#define ATRACE_TAG_LAST ATRACE_TAG_HAL +#define ATRACE_TAG_APP (1<<12) +#define ATRACE_TAG_LAST ATRACE_TAG_APP // Reserved for initialization. #define ATRACE_TAG_NOT_READY (1LL<<63) @@ -96,6 +98,14 @@ void atrace_setup(); */ void atrace_update_tags(); +/** + * Set whether the process is debuggable. By default the process is not + * considered debuggable. If the process is not debuggable then application- + * level tracing is not allowed unless the ro.debuggable system property is + * set to '1'. + */ +void atrace_set_debuggable(bool debuggable); + /** * Flag indicating whether setup has been completed, initialized to 0. * Nonzero indicates setup has completed. diff --git a/libcutils/trace.c b/libcutils/trace.c index 152ea6157..047f88941 100644 --- a/libcutils/trace.c +++ b/libcutils/trace.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -29,11 +30,81 @@ #define LOG_TAG "cutils-trace" #include -int32_t atrace_is_ready = 0; -int atrace_marker_fd = -1; -uint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY; -static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; -static pthread_mutex_t atrace_tags_mutex = PTHREAD_MUTEX_INITIALIZER; +int32_t atrace_is_ready = 0; +int atrace_marker_fd = -1; +uint64_t atrace_enabled_tags = ATRACE_TAG_NOT_READY; +static bool atrace_is_debuggable = false; +static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT; +static pthread_mutex_t atrace_tags_mutex = PTHREAD_MUTEX_INITIALIZER; + +// Set whether this process is debuggable, which determines whether +// application-level tracing is allowed when the ro.debuggable system property +// is not set to '1'. +void atrace_set_debuggable(bool debuggable) +{ + atrace_is_debuggable = debuggable; + atrace_update_tags(); +} + +// Check whether the given command line matches one of the comma-separated +// values listed in the app_cmdlines property. +static bool atrace_is_cmdline_match(const char* cmdline) { + char value[PROPERTY_VALUE_MAX]; + char* start = value; + + property_get("debug.atrace.app_cmdlines", value, ""); + + while (start != NULL) { + char* end = strchr(start, ','); + + if (end != NULL) { + *end = '\0'; + end++; + } + + if (strcmp(cmdline, start) == 0) { + return true; + } + + start = end; + } + + return false; +} + +// Determine whether application-level tracing is enabled for this process. +static bool atrace_is_app_tracing_enabled() +{ + bool sys_debuggable = false; + bool proc_debuggable = false; + char value[PROPERTY_VALUE_MAX]; + bool result = false; + + // Check whether the system is debuggable. + property_get("ro.debuggable", value, "0"); + if (value[0] == '1') { + sys_debuggable = true; + } + + if (sys_debuggable || atrace_is_debuggable) { + // Check whether tracing is enabled for this process. + FILE * file = fopen("/proc/self/cmdline", "r"); + if (file) { + char cmdline[4096]; + if (fgets(cmdline, sizeof(cmdline), file)) { + result = atrace_is_cmdline_match(cmdline); + } else { + ALOGE("Error reading cmdline: %s (%d)", strerror(errno), errno); + } + fclose(file); + } else { + ALOGE("Error opening /proc/self/cmdline: %s (%d)", strerror(errno), + errno); + } + } + + return result; +} // Read the sysprop and return the value tags should be set to static uint64_t atrace_get_property() @@ -52,6 +123,15 @@ static uint64_t atrace_get_property() ALOGE("Error parsing trace property: Number too large: %s", value); return 0; } + + // Only set the "app" tag if this process was selected for app-level debug + // tracing. + if (atrace_is_app_tracing_enabled()) { + tags |= ATRACE_TAG_APP; + } else { + tags &= ~ATRACE_TAG_APP; + } + return (tags | ATRACE_TAG_ALWAYS) & ATRACE_TAG_VALID_MASK; }