summaryrefslogtreecommitdiffstats
path: root/libcutils
diff options
context:
space:
mode:
Diffstat (limited to 'libcutils')
-rw-r--r--libcutils/Android.mk5
-rw-r--r--libcutils/fs.c1
-rw-r--r--libcutils/klog.c5
-rw-r--r--libcutils/trace.c186
-rw-r--r--libcutils/zygote.c38
5 files changed, 195 insertions, 40 deletions
diff --git a/libcutils/Android.mk b/libcutils/Android.mk
index 17b320f..5037705 100644
--- a/libcutils/Android.mk
+++ b/libcutils/Android.mk
@@ -121,6 +121,7 @@ LOCAL_SRC_FILES := $(commonSources) \
mq.c \
partition_utils.c \
qtaguid.c \
+ trace.c \
uevent.c
ifeq ($(TARGET_ARCH),arm)
@@ -145,7 +146,9 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := libcutils
-LOCAL_WHOLE_STATIC_LIBRARIES := libcutils
+# TODO: remove liblog as whole static library, once we don't have prebuilt that requires
+# liblog symbols present in libcutils.
+LOCAL_WHOLE_STATIC_LIBRARIES := libcutils liblog
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_CFLAGS += $(targetSmpFlag)
LOCAL_C_INCLUDES := $(libcutils_c_includes)
diff --git a/libcutils/fs.c b/libcutils/fs.c
index 1226d44..116526d 100644
--- a/libcutils/fs.c
+++ b/libcutils/fs.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <string.h>
#include <limits.h>
+#include <stdlib.h>
#define ALL_PERMS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO)
#define BUF_SIZE 64
diff --git a/libcutils/klog.c b/libcutils/klog.c
index b586a57..812af3b 100644
--- a/libcutils/klog.c
+++ b/libcutils/klog.c
@@ -35,6 +35,9 @@ void klog_set_level(int level) {
void klog_init(void)
{
static const char *name = "/dev/__kmsg__";
+
+ if (klog_fd >= 0) return; /* Already initialized */
+
if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
klog_fd = open(name, O_WRONLY);
fcntl(klog_fd, F_SETFD, FD_CLOEXEC);
@@ -50,7 +53,7 @@ void klog_write(int level, const char *fmt, ...)
va_list ap;
if (level > klog_level) return;
- if (klog_fd < 0) return;
+ if (klog_fd < 0) klog_init();
va_start(ap, fmt);
vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
diff --git a/libcutils/trace.c b/libcutils/trace.c
new file mode 100644
index 0000000..9754a44
--- /dev/null
+++ b/libcutils/trace.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <pthread.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <cutils/atomic.h>
+#include <cutils/compiler.h>
+#include <cutils/properties.h>
+#include <cutils/trace.h>
+
+#define LOG_TAG "cutils-trace"
+#include <cutils/log.h>
+
+volatile 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 volatile int32_t atrace_is_enabled = 1;
+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();
+}
+
+// Set whether tracing is enabled in this process. This is used to prevent
+// the Zygote process from tracing.
+void atrace_set_tracing_enabled(bool enabled)
+{
+ android_atomic_release_store(enabled ? 1 : 0, &atrace_is_enabled);
+ 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()
+{
+ char value[PROPERTY_VALUE_MAX];
+ char *endptr;
+ uint64_t tags;
+
+ property_get("debug.atrace.tags.enableflags", value, "0");
+ errno = 0;
+ tags = strtoull(value, &endptr, 0);
+ if (value[0] == '\0' || *endptr != '\0') {
+ ALOGE("Error parsing trace property: Not a number: %s", value);
+ return 0;
+ } else if (errno == ERANGE || tags == ULLONG_MAX) {
+ 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;
+}
+
+// Update tags if tracing is ready. Useful as a sysprop change callback.
+void atrace_update_tags()
+{
+ uint64_t tags;
+ if (CC_UNLIKELY(android_atomic_acquire_load(&atrace_is_ready))) {
+ if (android_atomic_acquire_load(&atrace_is_enabled)) {
+ tags = atrace_get_property();
+ pthread_mutex_lock(&atrace_tags_mutex);
+ atrace_enabled_tags = tags;
+ pthread_mutex_unlock(&atrace_tags_mutex);
+ } else {
+ // Tracing is disabled for this process, so we simply don't
+ // initialize the tags.
+ pthread_mutex_lock(&atrace_tags_mutex);
+ atrace_enabled_tags = ATRACE_TAG_NOT_READY;
+ pthread_mutex_unlock(&atrace_tags_mutex);
+ }
+ }
+}
+
+static void atrace_init_once()
+{
+ atrace_marker_fd = open("/sys/kernel/debug/tracing/trace_marker", O_WRONLY);
+ if (atrace_marker_fd == -1) {
+ ALOGE("Error opening trace file: %s (%d)", strerror(errno), errno);
+ atrace_enabled_tags = 0;
+ goto done;
+ }
+
+ atrace_enabled_tags = atrace_get_property();
+
+done:
+ android_atomic_release_store(1, &atrace_is_ready);
+}
+
+void atrace_setup()
+{
+ pthread_once(&atrace_once_control, atrace_init_once);
+}
diff --git a/libcutils/zygote.c b/libcutils/zygote.c
index 75ce3ba..37236e8 100644
--- a/libcutils/zygote.c
+++ b/libcutils/zygote.c
@@ -159,44 +159,6 @@ static int send_request(int fd, int sendStdio, int argc, const char **argv)
#endif /* HAVE_ANDROID_OS */
}
-int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
-{
- int fd;
- int pid;
- int err;
- const char *newargv[argc + 1];
-
- fd = socket_local_client(ZYGOTE_SOCKET,
- ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
-
- if (fd < 0) {
- return -1;
- }
-
- // The command socket is passed to the peer as close-on-exec
- // and will close when the peer dies
- newargv[0] = "--peer-wait";
- memcpy(newargv + 1, argv, argc * sizeof(*argv));
-
- pid = send_request(fd, 1, argc + 1, newargv);
-
- if (pid > 0 && post_run_func != NULL) {
- post_run_func(pid);
- }
-
- // Wait for socket to close
- do {
- int dummy;
- err = read(fd, &dummy, sizeof(dummy));
- } while ((err < 0 && errno == EINTR) || err != 0);
-
- do {
- err = close(fd);
- } while (err < 0 && errno == EINTR);
-
- return 0;
-}
-
/**
* Spawns a new dalvik instance via the Zygote process. The non-zygote
* arguments are passed to com.android.internal.os.RuntimeInit(). The