ART: Streaming trace mode

Add a streaming mode for tracing. Streaming uses a buffer of 16KB
and writes to the output when that buffer gets full. Streaming mode
can be enabled with -Xmethod-trace-stream and is currently not
exposed otherwise.

Add a python script that can parse the streaming format, which
simply contains strings for newly encountered threads and methods
inline, and create output that can be used with traceview.

Add Trace::Pause and Trace::Abort, which can pause and abort tracing.
Abort is different from Stop in that it does not write the data.

Add code to the zygote hooks JNI implementation that pauses tracing
before the fork, making sure that a child cannot clobber the parent's
data.

Add code to the zygote hooks JNI implementation that aborts old
tracing and starts new tracing in the child after the fork. Currently
base the output on the pid. This will not work on an unmodified
device, as the profiles directory is not generally writable, but
we do not have enough information at that point. Consider a scheme
that restarts tracing later.

Change-Id: I93c7bf87e35af582bdfdd3ecc7c52454514220dd
diff --git a/runtime/utils.cc b/runtime/utils.cc
index f13da8b..a303aa4 100644
--- a/runtime/utils.cc
+++ b/runtime/utils.cc
@@ -1440,32 +1440,58 @@
   }
 }
 
-std::string GetDalvikCacheOrDie(const char* subdir, const bool create_if_absent) {
+static std::string GetDalvikCacheImpl(const char* subdir,
+                                      const bool create_if_absent,
+                                      const bool abort_on_error) {
   CHECK(subdir != nullptr);
   const char* android_data = GetAndroidData();
   const std::string dalvik_cache_root(StringPrintf("%s/dalvik-cache/", android_data));
   const std::string dalvik_cache = dalvik_cache_root + subdir;
-  if (create_if_absent && !OS::DirectoryExists(dalvik_cache.c_str())) {
+  if (!OS::DirectoryExists(dalvik_cache.c_str())) {
+    if (!create_if_absent) {
+      // TODO: Check callers. Traditional behavior is to not to abort, even when abort_on_error.
+      return "";
+    }
+
     // Don't create the system's /data/dalvik-cache/... because it needs special permissions.
-    if (strcmp(android_data, "/data") != 0) {
-      int result = mkdir(dalvik_cache_root.c_str(), 0700);
-      if (result != 0 && errno != EEXIST) {
-        PLOG(FATAL) << "Failed to create dalvik-cache directory " << dalvik_cache_root;
-        return "";
+    if (strcmp(android_data, "/data") == 0) {
+      if (abort_on_error) {
+        LOG(FATAL) << "Failed to find dalvik-cache directory " << dalvik_cache
+                   << ", cannot create /data dalvik-cache.";
+        UNREACHABLE();
       }
-      result = mkdir(dalvik_cache.c_str(), 0700);
-      if (result != 0) {
+      return "";
+    }
+
+    int result = mkdir(dalvik_cache_root.c_str(), 0700);
+    if (result != 0 && errno != EEXIST) {
+      if (abort_on_error) {
+        PLOG(FATAL) << "Failed to create dalvik-cache root directory " << dalvik_cache_root;
+        UNREACHABLE();
+      }
+      return "";
+    }
+
+    result = mkdir(dalvik_cache.c_str(), 0700);
+    if (result != 0) {
+      if (abort_on_error) {
         PLOG(FATAL) << "Failed to create dalvik-cache directory " << dalvik_cache;
-        return "";
+        UNREACHABLE();
       }
-    } else {
-      LOG(FATAL) << "Failed to find dalvik-cache directory " << dalvik_cache;
       return "";
     }
   }
   return dalvik_cache;
 }
 
+std::string GetDalvikCache(const char* subdir, const bool create_if_absent) {
+  return GetDalvikCacheImpl(subdir, create_if_absent, false);
+}
+
+std::string GetDalvikCacheOrDie(const char* subdir, const bool create_if_absent) {
+  return GetDalvikCacheImpl(subdir, create_if_absent, true);
+}
+
 bool GetDalvikCacheFilename(const char* location, const char* cache_location,
                             std::string* filename, std::string* error_msg) {
   if (location[0] != '/') {