/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-thread", "handling " + ChunkHandler.name(type)); if (type == CHUNK_THCR) { handleTHCR(client, data); } else if (type == CHUNK_THDE) { handleTHDE(client, data); } else if (type == CHUNK_THST) { handleTHST(client, data); } else if (type == CHUNK_THNM) { handleTHNM(client, data); } else if (type == CHUNK_STKL) { handleSTKL(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } }
/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-prof", "handling " + ChunkHandler.name(type)); 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) { handleFAIL(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } }
/* * Handle a thread creation message. */ private void handleTEST(Client client, ByteBuffer data) { /* * Can't call data.array() on a read-only ByteBuffer, so we make * a copy. */ var copy = new byte[data.limit]; data.get(copy); Log.d("ddm-test", "Received:"); Log.hexDump("ddm-test", Log.LogLevel.DEBUG, copy, 0, copy.Length); }
/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-test", "handling " + ChunkHandler.name(type)); if (type == CHUNK_TEST) { handleTEST(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } }
/* * Handle a reply to our WAIT message. */ private static void handleWAIT(Client client, ByteBuffer data) { var reason = data.get(); Log.d("ddm-wait", "WAIT: reason=" + reason); ClientData cd = client.clientData; lock (cd) { cd.debuggerConnectionStatus = ClientData.DebuggerStatus.WAITING; } client.update(Client.CHANGE_DEBUGGER_STATUS); }
/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-appname", "handling " + ChunkHandler.name(type)); if (type == CHUNK_APNM) { Debug.Assert(!isReply); handleAPNM(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } }
/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-hello", "handling " + ChunkHandler.name(type)); if (type == CHUNK_HELO) { Debug.Assert(isReply); handleHELO(client, data); } else if (type == CHUNK_FEAT) { handleFEAT(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } }
/* * Handle a reply to our APNM message. */ private static void handleAPNM(Client client, ByteBuffer data) { int appNameLen; string appName; appNameLen = data.getInt(); appName = getString(data, appNameLen); Log.d("ddm-appname", "APNM: app='" + appName + "'"); ClientData cd = client.clientData; lock (cd) { cd.clientDescription = appName; } client = checkDebuggerPortForAppName(client, appName); if (client != null) { client.update(Client.CHANGE_NAME); } }
/// <summary> /// Create a new, empty packet, in "buf". /// </summary> internal JdwpPacket(ByteBuffer buf) { mBuffer = buf; mIsNew = true; }
/* * Handle a thread status update message. * * Response has: * (1b) header len * (1b) bytes per entry * (2b) thread count * Then, for each thread: * (4b) threadId (matches value from THCR) * (1b) thread status * (4b) tid * (4b) utime * (4b) stime */ private void handleTHST(Client client, ByteBuffer data) { int headerLen, bytesPerEntry, extraPerEntry; int threadCount; headerLen = (data.get() & 0xff); bytesPerEntry = (data.get() & 0xff); threadCount = data.getShort(); headerLen -= 4; // we've read 4 bytes while (headerLen-- > 0) { data.get(); } extraPerEntry = bytesPerEntry - 18; // we want 18 bytes Log.v("ddm-thread", "THST: threadCount=" + threadCount); /* * For each thread, extract the data, find the appropriate * client, and add it to the ClientData. */ for (int i = 0; i < threadCount; i++) { int threadId, status, tid, utime, stime; bool isDaemon = false; threadId = data.getInt(); status = data.get(); tid = data.getInt(); utime = data.getInt(); stime = data.getInt(); if (bytesPerEntry >= 18) { isDaemon = (data.get() != 0); } Log.v("ddm-thread", " id=" + threadId + ", status=" + status + ", tid=" + tid + ", utime=" + utime + ", stime=" + stime); ClientData cd = client.clientData; ThreadInfo threadInfo = cd.getThread(threadId); if (threadInfo != null) { threadInfo.updateThread(status, tid, utime, stime, isDaemon); } else { Log.d("ddms", "Thread with id=" + threadId + " not found"); } // slurp up any extra for (int slurp = extraPerEntry; slurp > 0; slurp--) { data.get(); } } client.update(Client.CHANGE_THREAD_DATA); }
/* * Handle a THNM (THread NaMe) message. We get one of these after * somebody calls Thread.setName() on a running thread. */ private void handleTHNM(Client client, ByteBuffer data) { int threadId, nameLen; string name; threadId = data.getInt(); nameLen = data.getInt(); name = getString(data, nameLen); Log.v("ddm-thread", "THNM: " + threadId + " '" + name + "'"); ThreadInfo threadInfo = client.clientData.getThread(threadId); if (threadInfo != null) { threadInfo.threadName = name; client.update(Client.CHANGE_THREAD_DATA); } else { Log.d("ddms", "Thread with id=" + threadId + " not found"); } }
/// <summary> /// Parse an incoming STKL. /// </summary> private void handleSTKL(Client client, ByteBuffer data) { StackTraceElement[] trace; int i, threadId, stackDepth; //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @SuppressWarnings("unused") int future; int future; future = data.getInt(); threadId = data.getInt(); Log.v("ddms", "STKL: " + threadId); /* un-serialize the StackTraceElement[] */ stackDepth = data.getInt(); trace = new StackTraceElement[stackDepth]; for (i = 0; i < stackDepth; i++) { string className, methodName, fileName; int len, lineNumber; len = data.getInt(); className = getString(data, len); len = data.getInt(); methodName = getString(data, len); len = data.getInt(); if (len == 0) { fileName = null; } else { fileName = getString(data, len); } lineNumber = data.getInt(); trace[i] = new StackTraceElement(className, methodName, fileName, lineNumber); } ThreadInfo threadInfo = client.clientData.getThread(threadId); if (threadInfo != null) { threadInfo.stackCall = trace; client.update(Client.CHANGE_THREAD_STACKTRACE); } else { Log.d("STKL", string.Format("Got stackcall for thread {0:D}, which does not exists (anymore?).", threadId)); //$NON-NLS-1$ } }
internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { handleUnknownChunk(client, type, data, isReply, msgId); }
/// <summary> /// Remove the handshake string from the buffer. /// /// On entry and exit, "position" is the #of bytes in the buffer. /// </summary> internal static void consumeHandshake(ByteBuffer buf) { // in theory, nothing else can have arrived, so this is overkill buf.flip(); // limit<-posn, posn<-0 buf.position = mHandshake.Length; buf.compact(); // shift posn...limit, posn<-pending data }
private void handleFAIL(Client client, ByteBuffer data) { /*int errorCode =*/ data.getInt(); int length = data.getInt() * 2; string message = null; if (length > 0) { var messageBuffer = new byte[length]; data.get(messageBuffer, 0, length); message = Encoding.Default.GetString(messageBuffer); } // this can be sent if // - MPRS failed (like wrong permission) // - MPSE failed for whatever reason string filename = client.clientData.pendingMethodProfiling; if (filename != null) { // reset the pending file. client.clientData.pendingMethodProfiling = null; // and notify of failure ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler; if (handler != null) { handler.onStartFailure(client, message); } } else { // this is MPRE // notify of failure ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler; if (handler != null) { handler.onEndFailure(client, message); } } // send a query to know the current status try { sendMPRQ(client); } catch (IOException e) { Log.e("HandleProfiling", e); } }
/// <summary> /// Receive response to query. /// </summary> private void handleMPRQ(Client client, ByteBuffer data) { var result = data.get(); if (result == 0) { client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.OFF; Log.d("ddm-prof", "Method profiling is not running"); } else { client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.ON; Log.d("ddm-prof", "Method profiling is running"); } client.update(Client.CHANGE_METHOD_PROFILING_STATUS); }
/* * Handle a thread death message. */ private void handleTHDE(Client client, ByteBuffer data) { int threadId; threadId = data.getInt(); Log.v("ddm-thread", "THDE: " + threadId); client.clientData.removeThread(threadId); client.update(Client.CHANGE_THREAD_DATA); }
/// <summary> /// Handle a reply to our FEAT request. /// </summary> private static void handleFEAT(Client client, ByteBuffer data) { int featureCount; int i; featureCount = data.getInt(); for (i = 0; i < featureCount; i++) { int len = data.getInt(); string feature = getString(data, len); client.clientData.addFeature(feature); Log.d("ddm-hello", "Feature: " + feature); } }
/// <summary> /// "Move" the packet data out of the buffer we're sitting on and into /// buf at the current position. /// </summary> internal void movePacket(ByteBuffer buf) { Log.v("ddms", "moving " + mLength + " bytes"); int oldPosn = mBuffer.position; mBuffer.position = (0); mBuffer.limit =(mLength); buf.put(mBuffer); mBuffer.position=(mLength); mBuffer.limit=(oldPosn); mBuffer.compact(); // shift posn...limit, posn<-pending data }
/// <summary> /// Copy the handshake string into the output buffer. /// /// On exit, "buf"s position will be advanced. /// </summary> internal static void putHandshake(ByteBuffer buf) { buf.put(mHandshake); }
/// <summary> /// Find the JDWP packet at the start of "buf". The start is known, /// but the length has to be parsed out. /// /// On entry, the packet data in "buf" must start at offset 0 and end /// at "position". "limit" should be set to the buffer capacity. This /// method does not alter "buf"s attributes. /// /// Returns a new JdwpPacket if a full one is found in the buffer. If /// not, returns null. Throws an exception if the data doesn't look like /// a valid JDWP packet. /// </summary> internal static JdwpPacket findPacket(ByteBuffer buf) { int count = buf.position; int length, id, flags, cmdSet, cmd; if (count < JDWP_HEADER_LEN) { return null; } ByteOrder oldOrder = buf.order; buf.order =(ChunkHandler.CHUNK_ORDER); length = buf.getInt(0x00); id = buf.getInt(0x04); flags = buf.get(0x08) & 0xff; cmdSet = buf.get(0x09) & 0xff; cmd = buf.get(0x0a) & 0xff; buf.order = oldOrder; if (length < JDWP_HEADER_LEN) { throw new BadPacketException(); } if (count < length) { return null; } JdwpPacket pkt = new JdwpPacket(buf); //pkt.mBuffer = buf; pkt.mLength = length; pkt.mId = id; pkt.mFlags = flags; if ((flags & REPLY_PACKET) == 0) { pkt.mCmdSet = cmdSet; pkt.mCmd = cmd; pkt.mErrCode = -1; } else { pkt.mCmdSet = -1; pkt.mCmd = -1; pkt.mErrCode = cmdSet | (cmd << 8); } return pkt; }
/// <summary> /// Like findPacket(), but when we're expecting the JDWP handshake. /// /// Returns one of: /// HANDSHAKE_GOOD - found handshake, looks good /// HANDSHAKE_BAD - found enough data, but it's wrong /// HANDSHAKE_NOTYET - not enough data has been read yet /// </summary> internal static int findHandshake(ByteBuffer buf) { int count = buf.position; int i; if (count < mHandshake.Length) { return HANDSHAKE_NOTYET; } for (i = mHandshake.Length - 1; i >= 0; --i) { if (buf.get(i) != mHandshake[i]) { return HANDSHAKE_BAD; } } return HANDSHAKE_GOOD; }
/* * Handle a reply to our HELO message. */ private static void handleHELO(Client client, ByteBuffer data) { int version, pid, vmIdentLen, appNameLen; string vmIdent, appName; version = data.getInt(); pid = data.getInt(); vmIdentLen = data.getInt(); appNameLen = data.getInt(); vmIdent = getString(data, vmIdentLen); appName = getString(data, appNameLen); Log.d("ddm-hello", "HELO: v=" + version + ", pid=" + pid + ", vm='" + vmIdent + "', app='" + appName + "'"); ClientData cd = client.clientData; lock (cd) { if (cd.pid == pid) { cd.vmIdentifier = vmIdent; cd.clientDescription = appName; cd.isDdmAware(true); } else { Log.e("ddm-hello", "Received pid (" + pid + ") does not match client pid (" + cd.pid + ")"); } } client = checkDebuggerPortForAppName(client, appName); if (client != null) { client.update(Client.CHANGE_NAME); } }
/// <summary> /// Handle notification that method profiling has finished writing /// data to disk. /// </summary> private void handleMPRE(Client client, ByteBuffer data) { // get the filename and make the client not have pending HPROF dump anymore. string filename = client.clientData.pendingMethodProfiling; client.clientData.pendingMethodProfiling = null; byte result = data.get(); // get the app-level handler for method tracing dump ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler; if (handler != null) { if (result == 0) { handler.onSuccess(filename, client); Log.d("ddm-prof", "Method profiling has finished"); } else { handler.onEndFailure(client, null); //message Log.w("ddm-prof", "Method profiling has failed (check device log)"); } } client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.OFF; client.update(Client.CHANGE_METHOD_PROFILING_STATUS); }
/// <summary> /// Handle incoming profiling data. The MPSE packet includes the /// complete .trace file. /// </summary> private void handleMPSE(Client client, ByteBuffer data) { ClientData.IMethodProfilingHandler handler = ClientData.methodProfilingHandler; if (handler != null) { var stuff = new byte[data.capacity]; data.get(stuff, 0, stuff.Length); Log.d("ddm-prof", "got trace file, size: " + stuff.Length + " bytes"); handler.onSuccess(stuff, client); } client.clientData.methodProfilingStatus = ClientData.MethodProfilingStatus.OFF; client.update(Client.CHANGE_METHOD_PROFILING_STATUS); }
/* * Handle a thread creation message. * * We should be tolerant of receiving a duplicate create message. (It * shouldn't happen with the current implementation.) */ private void handleTHCR(Client client, ByteBuffer data) { int threadId, nameLen; string name; threadId = data.getInt(); nameLen = data.getInt(); name = getString(data, nameLen); Log.v("ddm-thread", "THCR: " + threadId + " '" + name + "'"); client.clientData.addThread(threadId, name); client.update(Client.CHANGE_THREAD_DATA); }