auto import from //depot/cupcake/@135843
diff --git a/emulator/qtools/dmtrace.cpp b/emulator/qtools/dmtrace.cpp
new file mode 100644
index 0000000..6d9250a
--- /dev/null
+++ b/emulator/qtools/dmtrace.cpp
@@ -0,0 +1,254 @@
+// Copyright 2006 The Android Open Source Project
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <string.h>
+#include "dmtrace.h"
+
+static const short kVersion = 2;
+
+const DmTrace::Header DmTrace::header = {
+    0x574f4c53, kVersion, sizeof(DmTrace::Header), 0LL
+};
+
+static char *keyHeader = "*version\n" "2\n" "clock=thread-cpu\n";
+static char *keyThreadHeader = "*threads\n";
+static char *keyFunctionHeader = "*methods\n";
+static char *keyEnd = "*end\n";
+
+DmTrace::DmTrace() {
+    fData = NULL;
+    fTrace = NULL;
+    threads = new std::vector<ThreadRecord*>;
+    functions = new std::vector<FunctionRecord*>;
+}
+
+DmTrace::~DmTrace() {
+    delete threads;
+    delete functions;
+}
+
+void DmTrace::open(const char *dmtrace_file, uint64_t start_time)
+{
+    fTrace = fopen(dmtrace_file, "w");
+    if (fTrace == NULL) {
+        perror(dmtrace_file);
+        exit(1);
+    }
+
+    // Make a temporary file to write the data into.
+    char tmpData[32];
+    strcpy(tmpData, "/tmp/dmtrace-data-XXXXXX");
+    int data_fd = mkstemp(tmpData);
+    if (data_fd < 0) {
+        perror("Cannot create temporary file");
+        exit(1);
+    }
+
+    // Ensure it goes away on exit.
+    unlink(tmpData);
+    fData = fdopen(data_fd, "w+");
+    if (fData == NULL) {
+        perror("Can't make temp data file");
+        exit(1);
+    }
+
+    writeHeader(fData, start_time);
+}
+
+void DmTrace::close()
+{
+    if (fTrace == NULL)
+        return;
+    writeKeyFile(fTrace);
+
+    // Take down how much data we wrote to the temp data file.
+    long size = ftell(fData);
+    // Rewind the data file and append its contents to the trace file.
+    rewind(fData);
+    char *data = (char *)malloc(size);
+    fread(data, size, 1, fData);
+    fwrite(data, size, 1, fTrace);
+    free(data);
+    fclose(fData);
+    fclose(fTrace);
+}
+
+/*
+ * Write values to the binary data file.
+ */
+void DmTrace::write2LE(FILE* fstream, unsigned short val)
+{
+    putc(val & 0xff, fstream);
+    putc(val >> 8, fstream);
+}
+
+void DmTrace::write4LE(FILE* fstream, unsigned int val)
+{
+    putc(val & 0xff, fstream);
+    putc((val >> 8) & 0xff, fstream);
+    putc((val >> 16) & 0xff, fstream);
+    putc((val >> 24) & 0xff, fstream);
+}
+
+void DmTrace::write8LE(FILE* fstream, unsigned long long val)
+{
+    putc(val & 0xff, fstream);
+    putc((val >> 8) & 0xff, fstream);
+    putc((val >> 16) & 0xff, fstream);
+    putc((val >> 24) & 0xff, fstream);
+    putc((val >> 32) & 0xff, fstream);
+    putc((val >> 40) & 0xff, fstream);
+    putc((val >> 48) & 0xff, fstream);
+    putc((val >> 56) & 0xff, fstream);
+}
+
+void DmTrace::writeHeader(FILE *fstream, uint64_t startTime)
+{
+    write4LE(fstream, header.magic);
+    write2LE(fstream, header.version);
+    write2LE(fstream, header.offset);
+    write8LE(fstream, startTime);
+}
+
+void DmTrace::writeDataRecord(FILE *fstream, int threadId,
+                             unsigned int methodVal,
+                             unsigned int elapsedTime)
+{
+    write2LE(fstream, threadId);
+    write4LE(fstream, methodVal);
+    write4LE(fstream, elapsedTime);
+}
+
+void DmTrace::addFunctionEntry(int functionId, uint32_t cycle, uint32_t pid)
+{
+    writeDataRecord(fData, pid, functionId, cycle);
+}
+
+void DmTrace::addFunctionExit(int functionId, uint32_t cycle, uint32_t pid)
+{
+    writeDataRecord(fData, pid, functionId | 1, cycle);
+}
+
+void DmTrace::addFunction(int functionId, const char *name)
+{
+    FunctionRecord *rec = new FunctionRecord;
+    rec->id = functionId;
+    rec->name = name;
+    functions->push_back(rec);
+}
+
+void DmTrace::addFunction(int functionId, const char *clazz,
+                          const char *method, const char *sig)
+{
+    // Allocate space for all the strings, plus 2 tab separators plus null byte.
+    // We currently don't reclaim this space.
+    int len = strlen(clazz) + strlen(method) + strlen(sig) + 3;
+    char *name = new char[len];
+    sprintf(name, "%s\t%s\t%s", clazz, method, sig);
+
+    addFunction(functionId, name);
+}
+
+void DmTrace::parseAndAddFunction(int functionId, const char *name)
+{
+    // Parse the "name" string into "class", "method" and "signature".
+    // The "name" string should look something like this:
+    //   name = "java.util.LinkedList.size()I"
+    // and it will be parsed into this:
+    //   clazz = "java.util.LinkedList"
+    //   method = "size"
+    //   sig = "()I"
+
+    // Find the first parenthesis, the start of the signature.
+    char *paren = strchr(name, '(');
+
+    // If not found, then add the original name.
+    if (paren == NULL) {
+        addFunction(functionId, name);
+        return;
+    }
+
+    // Copy the signature
+    int len = strlen(paren) + 1;
+    char *sig = new char[len];
+    strcpy(sig, paren);
+
+    // Zero the parenthesis so that we can search backwards from the signature
+    *paren = 0;
+
+    // Search for the last period, the start of the method name
+    char *dot = strrchr(name, '.');
+
+    // If not found, then add the original name.
+    if (dot == NULL || dot == name) {
+        delete[] sig;
+        *paren = '(';
+        addFunction(functionId, name);
+        return;
+    }
+
+    // Copy the method, not including the dot
+    len = strlen(dot + 1) + 1;
+    char *method = new char[len];
+    strcpy(method, dot + 1);
+
+    // Zero the dot to delimit the class name
+    *dot = 0;
+
+    addFunction(functionId, name, method, sig);
+
+    // Free the space we allocated.
+    delete[] sig;
+    delete[] method;
+}
+
+void DmTrace::addThread(int threadId, const char *name)
+{
+    ThreadRecord *rec = new ThreadRecord;
+    rec->id = threadId;
+    rec->name = name;
+    threads->push_back(rec);
+}
+
+void DmTrace::updateName(int threadId, const char *name)
+{
+    std::vector<ThreadRecord*>::iterator iter;
+
+    for (iter = threads->begin(); iter != threads->end(); ++iter) {
+        if ((*iter)->id == threadId) {
+            (*iter)->name = name;
+            return;
+        }
+    }
+}
+
+void DmTrace::writeKeyFile(FILE *fstream)
+{
+    fwrite(keyHeader, strlen(keyHeader), 1, fstream);
+    writeThreads(fstream);
+    writeFunctions(fstream);
+    fwrite(keyEnd, strlen(keyEnd), 1, fstream);
+}
+
+void DmTrace::writeThreads(FILE *fstream)
+{
+    std::vector<ThreadRecord*>::iterator iter;
+
+    fwrite(keyThreadHeader, strlen(keyThreadHeader), 1, fstream);
+    for (iter = threads->begin(); iter != threads->end(); ++iter) {
+        fprintf(fstream, "%d\t%s\n", (*iter)->id, (*iter)->name);
+    }
+}
+
+void DmTrace::writeFunctions(FILE *fstream)
+{
+    std::vector<FunctionRecord*>::iterator iter;
+
+    fwrite(keyFunctionHeader, strlen(keyFunctionHeader), 1, fstream);
+    for (iter = functions->begin(); iter != functions->end(); ++iter) {
+        fprintf(fstream, "0x%x\t%s\n", (*iter)->id, (*iter)->name);
+    }
+}