summaryrefslogtreecommitdiff
path: root/core/java/android/view/ViewDebug.java
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2011-07-21 18:04:29 -0700
committerRomain Guy <romainguy@google.com>2011-07-21 18:04:29 -0700
commit9a8c5cefcab3d5dec6ff63f0e99553e1aa9a4af8 (patch)
tree14cf9618c5154178f85ab63101b166b089400aa2 /core/java/android/view/ViewDebug.java
parent7eabe55db6b113f83c2cefcd06812648927de877 (diff)
Ouput looper traces as traceview traces
Change-Id: I96c8e85fd7497d970febbf6f5aefc4ab903add8e
Diffstat (limited to 'core/java/android/view/ViewDebug.java')
-rw-r--r--core/java/android/view/ViewDebug.java163
1 files changed, 128 insertions, 35 deletions
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 5f61cbbf2d05..4acf48c6b316 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -25,6 +25,7 @@ import android.os.Debug;
import android.os.Environment;
import android.os.Looper;
import android.os.Message;
+import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.DisplayMetrics;
@@ -50,6 +51,9 @@ import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
@@ -453,24 +457,33 @@ public class ViewDebug {
}
private static class LooperProfiler implements Looper.Profiler, Printer {
- private static final int LOOPER_PROFILER_VERSION = 1;
-
private static final String LOG_TAG = "LooperProfiler";
+ private static final int TRACE_VERSION_NUMBER = 3;
+ private static final int ACTION_EXIT_METHOD = 0x1;
+ private static final int HEADER_SIZE = 32;
+ private static final String HEADER_MAGIC = "SLOW";
+ private static final short HEADER_RECORD_SIZE = (short) 14;
+
private final long mTraceWallStart;
private final long mTraceThreadStart;
private final ArrayList<Entry> mTraces = new ArrayList<Entry>(512);
- private final HashMap<String, Short> mTraceNames = new HashMap<String, Short>(32);
- private short mTraceId = 0;
+ private final HashMap<String, Integer> mTraceNames = new HashMap<String, Integer>(32);
+ private int mTraceId = 0;
private final String mPath;
- private final FileDescriptor mFileDescriptor;
+ private ParcelFileDescriptor mFileDescriptor;
LooperProfiler(String path, FileDescriptor fileDescriptor) {
mPath = path;
- mFileDescriptor = fileDescriptor;
+ try {
+ mFileDescriptor = ParcelFileDescriptor.dup(fileDescriptor);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+ throw new RuntimeException(e);
+ }
mTraceWallStart = SystemClock.currentTimeMicro();
mTraceThreadStart = SystemClock.currentThreadTimeMicro();
}
@@ -493,11 +506,11 @@ public class ViewDebug {
mTraces.add(entry);
}
- private short getTraceId(Message message) {
+ private int getTraceId(Message message) {
String name = message.getTarget().getMessageName(message);
- Short traceId = mTraceNames.get(name);
+ Integer traceId = mTraceNames.get(name);
if (traceId == null) {
- traceId = mTraceId++;
+ traceId = mTraceId++ << 4;
mTraceNames.put(name, traceId);
}
return traceId;
@@ -514,51 +527,131 @@ public class ViewDebug {
}
private void saveTraces() {
- FileOutputStream fos = new FileOutputStream(mFileDescriptor);
+ FileOutputStream fos = new FileOutputStream(mFileDescriptor.getFileDescriptor());
DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
try {
- out.writeInt(LOOPER_PROFILER_VERSION);
- out.writeLong(mTraceWallStart);
- out.writeLong(mTraceThreadStart);
-
- out.writeInt(mTraceNames.size());
- for (Map.Entry<String, Short> entry : mTraceNames.entrySet()) {
- saveTraceName(entry.getKey(), entry.getValue(), out);
- }
+ writeHeader(out, mTraceWallStart, mTraceNames, mTraces);
+ out.flush();
- out.writeInt(mTraces.size());
- for (Entry entry : mTraces) {
- saveTrace(entry, out);
- }
+ writeTraces(fos, out.size(), mTraceWallStart, mTraceThreadStart, mTraces);
Log.d(LOG_TAG, "Looper traces ready: " + mPath);
} catch (IOException e) {
- Log.e(LOG_TAG, "Could not write trace file: ", e);
+ Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
} finally {
try {
out.close();
} catch (IOException e) {
- // Ignore
+ Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
+ }
+ try {
+ mFileDescriptor.close();
+ } catch (IOException e) {
+ Log.e(LOG_TAG, "Could not write trace file " + mPath, e);
}
}
}
-
- private void saveTraceName(String name, short id, DataOutputStream out) throws IOException {
- out.writeShort(id);
- out.writeUTF(name);
+
+ private static void writeTraces(FileOutputStream out, long offset, long wallStart,
+ long threadStart, ArrayList<Entry> entries) throws IOException {
+
+ FileChannel channel = out.getChannel();
+
+ // Header
+ ByteBuffer buffer = ByteBuffer.allocateDirect(HEADER_SIZE);
+ buffer.put(HEADER_MAGIC.getBytes());
+ buffer = buffer.order(ByteOrder.LITTLE_ENDIAN);
+ buffer.putShort((short) TRACE_VERSION_NUMBER); // version
+ buffer.putShort((short) HEADER_SIZE); // offset to data
+ buffer.putLong(wallStart); // start time in usec
+ buffer.putShort(HEADER_RECORD_SIZE); // size of a record in bytes
+ // padding to 32 bytes
+ for (int i = 0; i < HEADER_SIZE - 18; i++) {
+ buffer.put((byte) 0);
+ }
+
+ buffer.flip();
+ channel.position(offset).write(buffer);
+
+ buffer = ByteBuffer.allocateDirect(14).order(ByteOrder.LITTLE_ENDIAN);
+ for (Entry entry : entries) {
+ buffer.putShort((short) 1); // we simulate only one thread
+ buffer.putInt(entry.traceId); // entering method
+ buffer.putInt((int) (entry.threadStart - threadStart));
+ buffer.putInt((int) (entry.wallStart - wallStart));
+
+ buffer.flip();
+ channel.write(buffer);
+ buffer.clear();
+
+ buffer.putShort((short) 1);
+ buffer.putInt(entry.traceId | ACTION_EXIT_METHOD); // exiting method
+ buffer.putInt((int) (entry.threadStart + entry.threadTime - threadStart));
+ buffer.putInt((int) (entry.wallStart + entry.wallTime - wallStart));
+
+ buffer.flip();
+ channel.write(buffer);
+ buffer.clear();
+ }
+
+ channel.close();
}
+
+ private static void writeHeader(DataOutputStream out, long start,
+ HashMap<String, Integer> names, ArrayList<Entry> entries) throws IOException {
+
+ Entry last = entries.get(entries.size() - 1);
+ long wallTotal = (last.wallStart + last.wallTime) - start;
+
+ startSection("version", out);
+ addValue(null, Integer.toString(TRACE_VERSION_NUMBER), out);
+ addValue("data-file-overflow", "false", out);
+ addValue("clock", "dual", out);
+ addValue("elapsed-time-usec", Long.toString(wallTotal), out);
+ addValue("num-method-calls", Integer.toString(entries.size()), out);
+ addValue("clock-call-overhead-nsec", "1", out);
+ addValue("vm", "dalvik", out);
+
+ startSection("threads", out);
+ addThreadId(1, "main", out);
+
+ startSection("methods", out);
+ addMethods(names, out);
+
+ startSection("end", out);
+ }
+
+ private static void addMethods(HashMap<String, Integer> names, DataOutputStream out)
+ throws IOException {
+
+ for (Map.Entry<String, Integer> name : names.entrySet()) {
+ out.writeBytes(String.format("0x%08x\tEventQueue\t%s\t()V\tLooper\t-2\n",
+ name.getValue(), name.getKey()));
+ }
+ }
+
+ private static void addThreadId(int id, String name, DataOutputStream out)
+ throws IOException {
- private void saveTrace(Entry entry, DataOutputStream out) throws IOException {
- out.writeShort(entry.traceId);
- out.writeLong(entry.wallStart);
- out.writeLong(entry.wallTime);
- out.writeLong(entry.threadStart);
- out.writeLong(entry.threadTime);
+ out.writeBytes(Integer.toString(id) + '\t' + name + '\n');
+ }
+
+ private static void addValue(String name, String value, DataOutputStream out)
+ throws IOException {
+
+ if (name != null) {
+ out.writeBytes(name + "=");
+ }
+ out.writeBytes(value + '\n');
+ }
+
+ private static void startSection(String name, DataOutputStream out) throws IOException {
+ out.writeBytes("*" + name + '\n');
}
static class Entry {
- short traceId;
+ int traceId;
long wallStart;
long wallTime;
long threadStart;