/// <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); } }
/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-nativeheap", "handling " + ChunkHandler.name(type)); if (type == CHUNK_NHGT) { handleNHGT(client, data); } else if (type == CHUNK_NHST) { // start chunk before any NHSG chunk(s) client.clientData.nativeHeapData.clearHeapData(); } else if (type == CHUNK_NHEN) { // end chunk after NHSG chunk(s) client.clientData.nativeHeapData.sealHeapData(); } else if (type == CHUNK_NHSG) { handleNHSG(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } client.update(Client.CHANGE_NATIVE_HEAP_DATA); }
/// <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> /// Client is ready. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public void clientReady(Client client) throws java.io.IOException internal override void clientReady(Client client) { if (client.heapUpdateEnabled) { //sendHPSG(client, WHEN_GC, WHAT_MERGE); sendHPIF(client, HPIF_WHEN_EVERY_GC); } }
/// <summary> /// Client is ready. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public void clientReady(Client client) throws java.io.IOException internal override void clientReady(Client client) { Log.d("ddm-thread", "Now ready: " + client); if (client.threadUpdateEnabled) { sendTHEN(client, true); } }
/* * 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> /// Send an EXIT request to the client. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void sendEXIT(Client client, int status) throws java.io.IOException public static void sendEXIT(Client client, int status) { ByteBuffer rawBuf = allocBuffer(4); JdwpPacket packet = new JdwpPacket(rawBuf); ByteBuffer buf = getChunkDataBuf(rawBuf); buf.putInt(status); finishChunkPacket(packet, CHUNK_EXIT, buf.position); Log.d("ddm-exit", "Sending " + name(CHUNK_EXIT) + ": " + status); client.sendAndConsume(packet, mInst); }
/// <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); } }
/// <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); } }
/* * 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> /// Handle chunks not recognized by handlers. The handleChunk() method /// in sub-classes should call this if the chunk type isn't recognized. /// </summary> protected internal virtual void handleUnknownChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { if (type == CHUNK_FAIL) { int errorCode, msgLen; string msg; errorCode = data.getInt(); msgLen = data.getInt(); msg = getString(data, msgLen); Log.w("ddms", "WARNING: failure code=" + errorCode + " msg=" + msg); } else { Log.w("ddms", "WARNING: received unknown chunk " + name(type) + ": len=" + data.limit + ", reply=" + isReply + ", msgId=0x" + msgId.toHexString()); } Log.w("ddms", " client " + client + ", handler " + this); }
/// <summary> /// Create a new Debugger object, configured to listen for connections /// on a specific port. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: Debugger(Client client, int listenPort) throws java.io.IOException internal Debugger(Client client, int listenPort) { mClient = client; mListenPort = listenPort; mListenChannel = ServerSocketChannel.open(); mListenChannel.configureBlocking(false); // required for Selector var addr = new DnsEndPoint("localhost", listenPort); //$NON-NLS-1$ mListenChannel.socket().ExclusiveAddressUse = false; // .reuseAddress = true; // enable SO_REUSEADDR mListenChannel.socket().Bind(addr); mReadBuffer = ByteBuffer.allocate(INITIAL_BUF_SIZE); mPreDataBuffer = ByteBuffer.allocate(PRE_DATA_BUF_SIZE); mConnState = ST_NOT_CONNECTED; Log.d("ddms", "Created: " + this.ToString()); }
/// <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> /// Sends HELLO-type commands to the VM after a good handshake. </summary> /// <param name="client"> </param> /// <param name="serverProtocolVersion"> </param> /// <exception cref="IOException"> </exception> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void sendHelloCommands(Client client, int serverProtocolVersion) throws java.io.IOException public static void sendHelloCommands(Client client, int serverProtocolVersion) { sendHELO(client, serverProtocolVersion); sendFEAT(client); HandleProfiling.sendMPRQ(client); }
/// <summary> /// Client went away. /// </summary> internal override void clientDisconnected(Client client) { Log.d("ddm-hello", "Now disconnected: " + client); }
/// <summary> /// Client is ready. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public void clientReady(Client client) throws java.io.IOException internal override void clientReady(Client client) { Log.d("ddm-hello", "Now ready: " + client); }
/// <summary> /// Send a FEAT request to the client. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void sendFEAT(Client client) throws java.io.IOException public static void sendFEAT(Client client) { ByteBuffer rawBuf = allocBuffer(0); JdwpPacket packet = new JdwpPacket(rawBuf); ByteBuffer buf = getChunkDataBuf(rawBuf); // no data finishChunkPacket(packet, CHUNK_FEAT, buf.position); Log.d("ddm-heap", "Sending " + name(CHUNK_FEAT)); client.sendAndConsume(packet, mInst); }
/// <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> /// Send a HELO request to the client. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public static void sendHELO(Client client, int serverProtocolVersion) throws java.io.IOException public static void sendHELO(Client client, int serverProtocolVersion) { ByteBuffer rawBuf = allocBuffer(4); JdwpPacket packet = new JdwpPacket(rawBuf); ByteBuffer buf = getChunkDataBuf(rawBuf); buf.putInt(serverProtocolVersion); finishChunkPacket(packet, CHUNK_HELO, buf.position); Log.d("ddm-hello", "Sending " + name(CHUNK_HELO) + " ID=0x" + packet.id.toHexString()); client.sendAndConsume(packet, mInst); }
/// <summary> /// Client is ready. The monitor thread calls this method on all /// handlers when the client is determined to be DDM-aware (usually /// after receiving a HELO response.) /// /// The handler can use this opportunity to initialize client-side /// activity. Because there's a fair chance we'll want to send a /// message to the client, this method can throw an IOException. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: abstract void clientReady(Client client) throws java.io.IOException; internal abstract void clientReady(Client client);
/* * Handle the response from our REcent Allocation Query message. */ private void handleREAQ(Client client, ByteBuffer data) { bool enabled; enabled = (data.get() != 0); Log.d("ddm-heap", "REAQ says: enabled=" + enabled); client.clientData.allocationStatus = enabled ? ClientData.AllocationTrackingStatus.ON : ClientData.AllocationTrackingStatus.OFF; client.update(Client.CHANGE_HEAP_ALLOCATION_STATUS); }
/// <summary> /// Client went away. /// </summary> internal override void clientDisconnected(Client client) { }
/// <summary> /// Client is ready. /// </summary> //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET: //ORIGINAL LINE: public void clientReady(Client client) throws java.io.IOException internal override void clientReady(Client client) { }
/* * Handle a REcent ALlocation response. * * Message header (all values big-endian): * (1b) message header len (to allow future expansion); includes itself * (1b) entry header len * (1b) stack frame len * (2b) number of entries * (4b) offset to string table from start of message * (2b) number of class name strings * (2b) number of method name strings * (2b) number of source file name strings * For each entry: * (4b) total allocation size * (2b) threadId * (2b) allocated object's class name index * (1b) stack depth * For each stack frame: * (2b) method's class name * (2b) method name * (2b) method source file * (2b) line number, clipped to 32767; -2 if native; -1 if no source * (xb) class name strings * (xb) method name strings * (xb) source file strings * * As with other DDM traffic, strings are sent as a 4-byte length * followed by UTF-16 data. */ private void handleREAL(Client client, ByteBuffer data) { Log.e("ddm-heap", "*** Received " + name(CHUNK_REAL)); int messageHdrLen, entryHdrLen, stackFrameLen; int numEntries, offsetToStrings; int numClassNames, numMethodNames, numFileNames; /* * Read the header. */ messageHdrLen = (data.get() & 0xff); entryHdrLen = (data.get() & 0xff); stackFrameLen = (data.get() & 0xff); numEntries = (data.getShort() & 0xffff); offsetToStrings = data.getInt(); numClassNames = (data.getShort() & 0xffff); numMethodNames = (data.getShort()& 0xffff); numFileNames = (data.getShort()& 0xffff); /* * Skip forward to the strings and read them. */ data.position = offsetToStrings; string[] classNames = new string[numClassNames]; string[] methodNames = new string[numMethodNames]; string[] fileNames = new string[numFileNames]; readStringTable(data, classNames); readStringTable(data, methodNames); //System.out.println("METHODS: " // + java.util.Arrays.deepToString(methodNames)); readStringTable(data, fileNames); /* * Skip back to a point just past the header and start reading * entries. */ data.position = messageHdrLen; List<AllocationInfo> list = new List<AllocationInfo>(numEntries); int allocNumber = numEntries; // order value for the entry. This is sent in reverse order. for (int i = 0; i < numEntries; i++) { int totalSize; int threadId, classNameIndex, stackDepth; totalSize = data.getInt(); threadId = (data.getShort() & 0xffff); classNameIndex = (data.getShort() & 0xffff); stackDepth = (data.get() & 0xff); /* we've consumed 9 bytes; gobble up any extra */ for (int skip = 9; skip < entryHdrLen; skip++) { data.get(); } StackTraceElement[] steArray = new StackTraceElement[stackDepth]; /* * Pull out the stack trace. */ for (int sti = 0; sti < stackDepth; sti++) { int methodClassNameIndex, methodNameIndex; int methodSourceFileIndex; short lineNumber; string methodClassName, methodName, methodSourceFile; methodClassNameIndex = (data.getShort() & 0xffff); methodNameIndex = (data.getShort()& 0xffff); methodSourceFileIndex = (data.getShort()& 0xffff); lineNumber = data.getShort(); methodClassName = classNames[methodClassNameIndex]; methodName = methodNames[methodNameIndex]; methodSourceFile = fileNames[methodSourceFileIndex]; steArray[sti] = new StackTraceElement(methodClassName, methodName, methodSourceFile, lineNumber); /* we've consumed 8 bytes; gobble up any extra */ for (int skip = 9; skip < stackFrameLen; skip++) { data.get(); } } list.Add(new AllocationInfo(allocNumber--, classNames[classNameIndex], totalSize, (short) threadId, steArray)); } client.clientData.allocations = list.ToArray(); client.update(Client.CHANGE_HEAP_ALLOCATIONS); }
/// <summary> /// Chunk handler entry point. /// </summary> internal override void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId) { Log.d("ddm-heap", "handling " + ChunkHandler.name(type)); if (type == CHUNK_HPIF) { handleHPIF(client, data); } else if (type == CHUNK_HPST) { handleHPST(client, data); } else if (type == CHUNK_HPEN) { handleHPEN(client, data); } else if (type == CHUNK_HPSG) { handleHPSG(client, data); } else if (type == CHUNK_HPDU) { handleHPDU(client, data); } else if (type == CHUNK_HPDS) { handleHPDS(client, data); } else if (type == CHUNK_REAQ) { handleREAQ(client, data); } else if (type == CHUNK_REAL) { handleREAL(client, data); } else { handleUnknownChunk(client, type, data, isReply, msgId); } }
/// <summary> /// Client has gone away. Can be used to clean up any resources /// associated with this client connection. /// </summary> internal abstract void clientDisconnected(Client client);
/* * 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 an incoming chunk. The data, of chunk type "type", begins /// at the start of "data" and continues to data.limit(). /// /// If "isReply" is set, then "msgId" will be the ID of the request /// we sent to the client. Otherwise, it's the ID generated by the /// client for this event. Note that it's possible to receive chunks /// in reply packets for which we are not registered. /// /// The handler may not modify the contents of "data". /// </summary> internal abstract void handleChunk(Client client, int type, ByteBuffer data, bool isReply, int msgId);
/// <summary> /// Check that the client is opened with the proper debugger port for the /// specified application name, and if not, reopen it. </summary> /// <param name="client"> </param> /// <param name="uiThread"> </param> /// <param name="appName"> /// @return </param> protected internal static Client checkDebuggerPortForAppName(Client client, string appName) { DebugPortManager.IDebugPortProvider provider = DebugPortManager.provider; if (provider != null) { Device device = client.deviceImpl; int newPort = provider.getPort(device, appName); if (newPort != DebugPortManager.DebugPortProvider.NO_STATIC_PORT && newPort != client.debuggerListenPort) { AndroidDebugBridge bridge = AndroidDebugBridge.bridge; if (bridge != null) { DeviceMonitor deviceMonitor = bridge.deviceMonitor; if (deviceMonitor != null) { deviceMonitor.addClientToDropAndReopen(client, newPort); client = null; } } } } return client; }