From 99cb03c8593d49efdf70cba8adc84231789dae07 Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Tue, 26 Jan 2010 07:37:22 -0800 Subject: Strawman support for streaming method profiling. This will send MPSS/MPSE packets instead of MPRS/MPRE when the client VM supports them. At least, it would if the property check weren't hard-wired to false, which is done because the MPSE handling in DDMS is incomplete (currently just dumps the first 100 chars so you can see that it really got something). For bug 2160407. --- .../libs/ddmlib/src/com/android/ddmlib/Client.java | 17 ++++-- .../ddmlib/src/com/android/ddmlib/ClientData.java | 6 +++ .../src/com/android/ddmlib/HandleProfiling.java | 62 ++++++++++++++++++++++ 3 files changed, 81 insertions(+), 4 deletions(-) diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java b/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java index d05fa14..52c9506 100644 --- a/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java +++ b/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java @@ -241,13 +241,22 @@ public class Client { } public void toggleMethodProfiling() { + boolean canStream = false; //mClientData.hasFeature(ClientData.FEATURE_PROFILING_STREAMING); try { if (mClientData.getMethodProfilingStatus() == MethodProfilingStatus.ON) { - HandleProfiling.sendMPRE(this); + if (canStream) { + HandleProfiling.sendMPSE(this); + } else { + HandleProfiling.sendMPRE(this); + } } else { - String file = "/sdcard/" + mClientData.getClientDescription().replaceAll("\\:.*", "") + - ".trace"; - HandleProfiling.sendMPRS(this, file, 8*1024*1024, 0 /*flags*/); + if (canStream) { + HandleProfiling.sendMPSS(this, 8*1024*1024, 0 /*flags*/); + } else { + String file = "/sdcard/" + mClientData.getClientDescription().replaceAll("\\:.*", "") + + ".trace"; + HandleProfiling.sendMPRS(this, file, 8*1024*1024, 0 /*flags*/); + } } } catch (IOException e) { Log.w("ddms", "Toggle method profiling failed"); diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java b/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java index 356f5d0..53e1352 100644 --- a/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java +++ b/ddms/libs/ddmlib/src/com/android/ddmlib/ClientData.java @@ -124,6 +124,12 @@ public class ClientData { public final static String FEATURE_PROFILING = "method-trace-profiling"; // $NON-NLS-1$ /** + * String for feature enabling direct streaming of method profiling data + * @see #hasFeature(String) + */ + public final static String FEATURE_PROFILING_STREAMING = "method-trace-profiling-streaming"; // $NON-NLS-1$ + + /** * String for feature allowing to dump hprof files * @see #hasFeature(String) */ diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java b/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java index 3b69973..fcc1d26 100644 --- a/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java +++ b/ddms/libs/ddmlib/src/com/android/ddmlib/HandleProfiling.java @@ -29,6 +29,8 @@ final class HandleProfiling extends ChunkHandler { public static final int CHUNK_MPRS = type("MPRS"); public static final int CHUNK_MPRE = type("MPRE"); + public static final int CHUNK_MPSS = type("MPSS"); + public static final int CHUNK_MPSE = type("MPSE"); public static final int CHUNK_MPRQ = type("MPRQ"); public static final int CHUNK_FAIL = type("FAIL"); @@ -41,6 +43,7 @@ final class HandleProfiling extends ChunkHandler { */ public static void register(MonitorThread mt) { mt.registerChunkHandler(CHUNK_MPRE, mInst); + mt.registerChunkHandler(CHUNK_MPSE, mInst); mt.registerChunkHandler(CHUNK_MPRQ, mInst); } @@ -67,6 +70,8 @@ final class HandleProfiling extends ChunkHandler { if (type == CHUNK_MPRE) { handleMPRE(client, data); + } else if (type == CHUNK_MPSE) { + handleMPSE(client, data); } else if (type == CHUNK_MPRQ) { handleMPRQ(client, data); } else if (type == CHUNK_FAIL) { @@ -160,6 +165,63 @@ final class HandleProfiling extends ChunkHandler { } /** + * Send a MPSS (Method Profiling Streaming Start) request to the client. + * + * The arguments to this method will eventually be passed to + * android.os.Debug.startMethodTracing() on the device. + * + * @param bufferSize is the desired buffer size in bytes (8MB is good) + * @param flags see startMethodTracing() docs; use 0 for default behavior + */ + public static void sendMPSS(Client client, int bufferSize, + int flags) throws IOException { + + ByteBuffer rawBuf = allocBuffer(2*4); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + buf.putInt(bufferSize); + buf.putInt(flags); + + finishChunkPacket(packet, CHUNK_MPSS, buf.position()); + Log.d("ddm-prof", "Sending " + name(CHUNK_MPSS) + + "', size=" + bufferSize + ", flags=" + flags); + client.sendAndConsume(packet, mInst); + + // send a status query. this ensure that the status is properly updated if for some + // reason starting the tracing failed. + sendMPRQ(client); + } + + /** + * Send a MPSE (Method Profiling Streaming End) request to the client. + */ + public static void sendMPSE(Client client) throws IOException { + ByteBuffer rawBuf = allocBuffer(0); + JdwpPacket packet = new JdwpPacket(rawBuf); + ByteBuffer buf = getChunkDataBuf(rawBuf); + + // no data + + finishChunkPacket(packet, CHUNK_MPSE, buf.position()); + Log.d("ddm-prof", "Sending " + name(CHUNK_MPSE)); + client.sendAndConsume(packet, mInst); + } + + /** + * Handle incoming profiling data. The MPSE packet includes the + * complete .trace file. + */ + private void handleMPSE(Client client, ByteBuffer data) { + // TODO + byte[] stuff = new byte[Math.min(100, data.capacity())]; + data.get(stuff, 0, stuff.length); + String sample = new String(stuff); + Log.e("ddm-prof", "GOT MPSE (" + data.capacity() + " bytes): '" + + sample + "' ..."); + } + + /** * Send a MPRQ (Method PRofiling Query) request to the client. */ public static void sendMPRQ(Client client) throws IOException { -- cgit v1.1