Example #1
0
        /// <summary>
        /// Send a DDM packet to the client.
        ///
        /// Ideally, we can do this with a single channel write.  If that doesn't
        /// happen, we have to prevent anybody else from writing to the channel
        /// until this packet completes, so we synchronize on the channel.
        ///
        /// Another goal is to avoid unnecessary buffer copies, so we write
        /// directly out of the JdwpPacket's ByteBuffer.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: void sendAndConsume(JdwpPacket packet, ChunkHandler replyHandler) throws java.io.IOException
        internal virtual void sendAndConsume(JdwpPacket packet, ChunkHandler replyHandler)
        {
            if (mChan == null)
            {
                // can happen for e.g. THST packets
                Log.v("ddms", "Not sending packet -- client is closed");
                return;
            }

            if (replyHandler != null)
            {
                /*
                 * Add the ID to the list of outstanding requests.  We have to do
                 * this before sending the packet, in case the response comes back
                 * before our thread returns from the packet-send function.
                 */
                addRequestId(packet.id, replyHandler);
            }

            lock (mChan)
            {
                try
                {
                    packet.writeAndConsume(mChan);
                }
                catch (IOException ioe)
                {
                    removeRequestId(packet.id);
                    throw ioe;
                }
            }
        }
Example #2
0
        /// <summary>
        /// Initiate the JDWP handshake.
        ///
        /// On failure, closes the socket and returns false.
        /// </summary>
        internal virtual bool sendHandshake()
        {
            Debug.Assert(mWriteBuffer.position == 0);

            try
            {
                // assume write buffer can hold 14 bytes
                JdwpPacket.putHandshake(mWriteBuffer);
                int expectedLen = mWriteBuffer.position;
                mWriteBuffer.flip();
                if (mChan.write(mWriteBuffer) != expectedLen)
                {
                    throw new IOException("partial handshake write");
                }
            }
            catch (IOException ioe)
            {
                Log.e("ddms-client", "IO error during handshake: " + ioe.Message);
                mConnState = ST_ERROR;
                close(true);                 // notify
                return(false);
            }
            finally
            {
                mWriteBuffer.clear();
            }

            mConnState = ST_AWAIT_SHAKE;

            return(true);
        }
Example #3
0
        /// <summary>
        /// Send the handshake to the debugger.  We also send along any packets
        /// we already received from the client (usually just a VM_START event,
        /// if anything at all).
        /// </summary>
        private /*synchronized*/ void sendHandshake()
        {
            ByteBuffer tempBuffer = ByteBuffer.allocate(JdwpPacket.HANDSHAKE_LEN);

            JdwpPacket.putHandshake(tempBuffer);
            int expectedLength = tempBuffer.position;

            tempBuffer.flip();
            if (mChannel.write(tempBuffer) != expectedLength)
            {
                throw new IOException("partial handshake write");
            }

            expectedLength = mPreDataBuffer.position;
            if (expectedLength > 0)
            {
                Log.d("ddms", "Sending " + mPreDataBuffer.position + " bytes of saved data");
                mPreDataBuffer.flip();
                if (mChannel.write(mPreDataBuffer) != expectedLength)
                {
                    throw new IOException("partial pre-data write");
                }
                mPreDataBuffer.clear();
            }
        }
Example #4
0
        /*
         * We have incoming data from the debugger. Forward it to the client.
         */
        private void processDebuggerData(SelectionKey key)
        {
            Debugger dbg = (Debugger)key.attachment();

            try
            {
                /*
                 * Read pending data.
                 */
                dbg.read();

                /*
                 * See if we have a full packet in the buffer. It's possible we have
                 * more than one packet, so we have to loop.
                 */
                JdwpPacket packet = dbg.jdwpPacket;
                while (packet != null)
                {
                    Log.v("ddms", "Forwarding dbg req 0x" + packet.id.toHexString() + " to " + dbg.client);

                    dbg.forwardPacketToClient(packet);

                    packet = dbg.jdwpPacket;
                }
            }
            catch (IOException)
            {
                /*
                 * Close data connection; automatically un-registers dbg from
                 * selector. The failure could be caused by the debugger going away,
                 * or by the client going away and failing to accept our data.
                 * Either way, the debugger connection does not need to exist any
                 * longer. We also need to recycle the connection to the client, so
                 * that the VM sees the debugger disconnect. For a DDM-aware client
                 * this won't be necessary, and we can just send a "debugger
                 * disconnected" message.
                 */
                Log.d("ddms", "Closing connection to debugger " + dbg);
                dbg.closeData();
                Client client = dbg.client;
                if (client.ddmAware)
                {
                    // TODO: soft-disconnect DDM-aware clients
                    Log.d("ddms", " (recycling client connection as well)");

                    // we should drop the client, but also attempt to reopen it.
                    // This is done by the DeviceMonitor.
                    client.deviceImpl.monitor.addClientToDropAndReopen(client, DebugPortManager.DebugPortProvider.NO_STATIC_PORT);
                }
                else
                {
                    Log.d("ddms", " (recycling client connection as well)");
                    // we should drop the client, but also attempt to reopen it.
                    // This is done by the DeviceMonitor.
                    client.deviceImpl.monitor.addClientToDropAndReopen(client, DebugPortManager.DebugPortProvider.NO_STATIC_PORT);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Write the chunk header at the start of the chunk.
        ///
        /// Pass in the byte buffer returned by JdwpPacket.getPayload().
        /// </summary>
        internal static void finishChunkPacket(JdwpPacket packet, int type, int chunkLen)
        {
            ByteBuffer buf = packet.payload;

            buf.putInt(0x00, type);
            buf.putInt(0x04, chunkLen);

            packet.finishPacket(CHUNK_HEADER_LEN + chunkLen);
        }
Example #6
0
        /// <summary>
        /// Sends an HPDS request to the client.
        ///
        /// We will get an HPDS response when the heap dump has completed.  On
        /// failure we get a generic failure response.
        ///
        /// This is more expensive for the device than HPDU, because the entire
        /// heap dump is held in RAM instead of spooled out to a temp file.  On
        /// the other hand, permission to write to /sdcard is not required.
        /// </summary>
        /// <param name="fileName"> name of output file (on device) </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendHPDS(Client client) throws java.io.IOException
        public static void sendHPDS(Client client)
        {
            ByteBuffer rawBuf = allocBuffer(0);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            finishChunkPacket(packet, CHUNK_HPDS, buf.position);
            Log.d("ddm-heap", "Sending " + name(CHUNK_HPDS));
            client.sendAndConsume(packet, mInst);
        }
Example #7
0
		/// <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);
		}
Example #8
0
        /// <summary>
        /// Send a MPRQ (Method PRofiling Query) request to the client.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendMPRQ(Client client) throws java.io.IOException
        public static void sendMPRQ(Client client)
        {
            ByteBuffer rawBuf = allocBuffer(0);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            // no data

            finishChunkPacket(packet, CHUNK_MPRQ, buf.position);
            Log.d("ddm-prof", "Sending " + name(CHUNK_MPRQ));
            client.sendAndConsume(packet, mInst);
        }
Example #9
0
        /// <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);
        }
Example #10
0
        /// <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);
        }
Example #11
0
        /// <summary>
        /// Send an HPIF (HeaP InFo) request to the client.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendHPIF(Client client, int when) throws java.io.IOException
        public static void sendHPIF(Client client, int when)
        {
            ByteBuffer rawBuf = allocBuffer(1);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            buf.put((byte)when);

            finishChunkPacket(packet, CHUNK_HPIF, buf.position);
            Log.d("ddm-heap", "Sending " + name(CHUNK_HPIF) + ": when=" + when);
            client.sendAndConsume(packet, mInst);
        }
Example #12
0
 /// <summary>
 /// An earlier request resulted in a failure.  This is the expected
 /// response to a HELO message when talking to a non-DDM client.
 /// </summary>
 internal virtual void packetFailed(JdwpPacket reply)
 {
     if (mConnState == ST_NEED_DDM_PKT)
     {
         Log.d("ddms", "Marking " + this + " as non-DDM client");
         mConnState = ST_NOT_DDM;
     }
     else if (mConnState != ST_NOT_DDM)
     {
         Log.w("ddms", "WEIRD: got JDWP failure packet on DDM req");
     }
 }
Example #13
0
        /// <summary>
        /// Sends a REAE (REcent Allocation Enable) request to the client.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendREAE(Client client, boolean enable) throws java.io.IOException
        public static void sendREAE(Client client, bool enable)
        {
            ByteBuffer rawBuf = allocBuffer(1);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            buf.put((byte)(enable ? 1 : 0));

            finishChunkPacket(packet, CHUNK_REAE, buf.position);
            Log.d("ddm-heap", "Sending " + name(CHUNK_REAE) + ": " + enable);
            client.sendAndConsume(packet, mInst);
        }
Example #14
0
        /// <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);
        }
Example #15
0
        /*
         * Send a THST request to the specified client.
         */
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void sendTHST(Client client) throws java.io.IOException
        private static void sendTHST(Client client)
        {
            ByteBuffer rawBuf = allocBuffer(0);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            // nothing much to say

            finishChunkPacket(packet, CHUNK_THST, buf.position);
            Log.d("ddm-thread", "Sending " + name(CHUNK_THST));
            client.sendAndConsume(packet, mInst);
        }
Example #16
0
        /// <summary>
        /// Sends an HPDU request to the client.
        ///
        /// We will get an HPDU response when the heap dump has completed.  On
        /// failure we get a generic failure response.
        /// </summary>
        /// <param name="fileName"> name of output file (on device) </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendHPDU(Client client, String fileName) throws java.io.IOException
        public static void sendHPDU(Client client, string fileName)
        {
            ByteBuffer rawBuf = allocBuffer(4 + fileName.Length * 2);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            buf.putInt(fileName.Length);
            putString(buf, fileName);

            finishChunkPacket(packet, CHUNK_HPDU, buf.position);
            Log.d("ddm-heap", "Sending " + name(CHUNK_HPDU) + " '" + fileName + "'");
            client.sendAndConsume(packet, mInst);
            client.clientData.pendingHprofDump = fileName;
        }
Example #17
0
        /// <summary>
        /// Forward the packet to the debugger (if still connected to one).
        ///
        /// Consumes the packet.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: void forwardPacketToDebugger(JdwpPacket packet) throws java.io.IOException
        internal virtual void forwardPacketToDebugger(JdwpPacket packet)
        {
            Debugger dbg = mDebugger;

            if (dbg == null)
            {
                Log.d("ddms", "Discarding packet");
                packet.consume();
            }
            else
            {
                dbg.sendAndConsume(packet);
            }
        }
Example #18
0
        /// <summary>
        /// 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.
        /// </summary>
        /// <param name="bufferSize"> is the desired buffer size in bytes (8MB is good) </param>
        /// <param name="flags"> see startMethodTracing() docs; use 0 for default behavior </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendMPSS(Client client, int bufferSize, int flags) throws java.io.IOException
        public static void sendMPSS(Client client, int bufferSize, int flags)
        {
            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);
        }
Example #19
0
        /*
         * Process an incoming DDM packet. If this is a reply to an earlier request,
         * "handler" will be set to the handler responsible for the original
         * request. The spec allows a JDWP message to include multiple DDM chunks.
         */
        private void callHandler(Client client, JdwpPacket packet, ChunkHandler handler)
        {
            // on first DDM packet received, broadcast a "ready" message
            if (!client.ddmSeen())
            {
                broadcast(CLIENT_READY, client);
            }

            ByteBuffer buf = packet.payload;
            int        type, length;
            bool       reply = true;

            type   = buf.getInt();
            length = buf.getInt();

            if (handler == null)
            {
                // not a reply, figure out who wants it
                lock (mHandlerMap)
                {
                    handler = mHandlerMap[type];
                    reply   = false;
                }
            }

            if (handler == null)
            {
                Log.w("ddms", "Received unsupported chunk type " + ChunkHandler.name(type) + " (len=" + length + ")");
            }
            else
            {
                Log.d("ddms", "Calling handler for " + ChunkHandler.name(type) + " [" + handler + "] (len=" + length + ")");
                ByteBuffer ibuf  = buf.slice();
                ByteBuffer roBuf = ibuf.asReadOnlyBuffer();                 // enforce R/O
                roBuf.order = ChunkHandler.CHUNK_ORDER;
                // do the handling of the chunk synchronized on the client list
                // to be sure there's no concurrency issue when we look for HOME
                // in hasApp()
                lock (mClientList)
                {
                    handler.handleChunk(client, type, roBuf, reply, packet.id);
                }
            }
        }
Example #20
0
        /// <summary>
        /// Send a THEN (THread notification ENable) request to the client.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendTHEN(Client client, boolean enable) throws java.io.IOException
        public static void sendTHEN(Client client, bool enable)
        {
            ByteBuffer rawBuf = allocBuffer(1);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            if (enable)
            {
                buf.put(1);
            }
            else
            {
                buf.put(0);
            }

            finishChunkPacket(packet, CHUNK_THEN, buf.position);
            Log.d("ddm-thread", "Sending " + name(CHUNK_THEN) + ": " + enable);
            client.sendAndConsume(packet, mInst);
        }
Example #21
0
 /// <summary>
 /// Send a packet to the debugger.
 ///
 /// Ideally, we can do this with a single channel write.  If that doesn't
 /// happen, we have to prevent anybody else from writing to the channel
 /// until this packet completes, so we synchronize on the channel.
 ///
 /// Another goal is to avoid unnecessary buffer copies, so we write
 /// directly out of the JdwpPacket's ByteBuffer.
 ///
 /// We must synchronize on "mChannel" before writing to it.  We want to
 /// coordinate the buffered data with mChannel creation, so this whole
 /// method is synchronized.
 /// </summary>
 /*lock*/
 internal void sendAndConsume(JdwpPacket packet)
 {
     if (mChannel == null)
     {
         /*
          * Buffer this up so we can send it to the debugger when it
          * finally does connect.  This is essential because the VM_START
          * message might be telling the debugger that the VM is
          * suspended.  The alternative approach would be for us to
          * capture and interpret VM_START and send it later if we
          * didn't choose to un-suspend the VM for our own purposes.
          */
         Log.d("ddms", "Saving packet 0x" + packet.id.toHexString());
         packet.movePacket(mPreDataBuffer);
     }
     else
     {
         packet.writeAndConsume(mChannel);
     }
 }
Example #22
0
        /// <summary>
        /// Send a STKL (STacK List) request to the client.  The VM will suspend
        /// the target thread, obtain its stack, and return it.  If the thread
        /// is no longer running, a failure result will be returned.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendSTKL(Client client, int threadId) throws java.io.IOException
        public static void sendSTKL(Client client, int threadId)
        {
            /*
             *          if (false)
             *          {
             *                  Log.d("ddm-thread", "would send STKL " + threadId);
             *                  return;
             *          }
             */

            ByteBuffer rawBuf = allocBuffer(4);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            buf.putInt(threadId);

            finishChunkPacket(packet, CHUNK_STKL, buf.position);
            Log.d("ddm-thread", "Sending " + name(CHUNK_STKL) + ": " + threadId);
            client.sendAndConsume(packet, mInst);
        }
Example #23
0
        /// <summary>
        /// Send a MPRS (Method PRofiling Start) request to the client.
        ///
        /// The arguments to this method will eventually be passed to
        /// android.os.Debug.startMethodTracing() on the device.
        /// </summary>
        /// <param name="fileName"> is the name of the file to which profiling data
        ///          will be written (on the device); it will have <seealso cref="DdmConstants#DOT_TRACE"/>
        ///          appended if necessary </param>
        /// <param name="bufferSize"> is the desired buffer size in bytes (8MB is good) </param>
        /// <param name="flags"> see startMethodTracing() docs; use 0 for default behavior </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendMPRS(Client client, String fileName, int bufferSize, int flags) throws java.io.IOException
        public static void sendMPRS(Client client, string fileName, int bufferSize, int flags)
        {
            ByteBuffer rawBuf = allocBuffer(3 * 4 + fileName.Length * 2);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            buf.putInt(bufferSize);
            buf.putInt(flags);
            buf.putInt(fileName.Length);
            putString(buf, fileName);

            finishChunkPacket(packet, CHUNK_MPRS, buf.position);
            Log.d("ddm-prof", "Sending " + name(CHUNK_MPRS) + " '" + fileName + "', size=" + bufferSize + ", flags=" + flags);
            client.sendAndConsume(packet, mInst);

            // record the filename we asked for.
            client.clientData.pendingMethodProfiling = fileName;

            // send a status query. this ensure that the status is properly updated if for some
            // reason starting the tracing failed.
            sendMPRQ(client);
        }
Example #24
0
        /// <summary>
        /// Send an NHGT (Native Thread GeT) request to the client.
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendNHGT(Client client) throws java.io.IOException
        public static void sendNHGT(Client client)
        {
            ByteBuffer rawBuf = allocBuffer(0);
            JdwpPacket packet = new JdwpPacket(rawBuf);
            ByteBuffer buf    = getChunkDataBuf(rawBuf);

            // no data in request message

            finishChunkPacket(packet, CHUNK_NHGT, buf.position);
            Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHGT));
            client.sendAndConsume(packet, mInst);

            rawBuf = allocBuffer(2);
            packet = new JdwpPacket(rawBuf);
            buf    = getChunkDataBuf(rawBuf);

            buf.put(HandleHeap.WHEN_DISABLE);
            buf.put(HandleHeap.WHAT_OBJ);

            finishChunkPacket(packet, CHUNK_NHSG, buf.position);
            Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHSG));
            client.sendAndConsume(packet, mInst);
        }
Example #25
0
		/// <summary>
		/// Write the chunk header at the start of the chunk.
		/// 
		/// Pass in the byte buffer returned by JdwpPacket.getPayload().
		/// </summary>
		internal static void finishChunkPacket(JdwpPacket packet, int type, int chunkLen)
		{
			ByteBuffer buf = packet.payload;

			buf.putInt(0x00, type);
			buf.putInt(0x04, chunkLen);

			packet.finishPacket(CHUNK_HEADER_LEN + chunkLen);
		}
Example #26
0
		/// <summary>
		/// Send a MPRS (Method PRofiling Start) request to the client.
		/// 
		/// The arguments to this method will eventually be passed to
		/// android.os.Debug.startMethodTracing() on the device.
		/// </summary>
		/// <param name="fileName"> is the name of the file to which profiling data
		///          will be written (on the device); it will have <seealso cref="DdmConstants#DOT_TRACE"/>
		///          appended if necessary </param>
		/// <param name="bufferSize"> is the desired buffer size in bytes (8MB is good) </param>
		/// <param name="flags"> see startMethodTracing() docs; use 0 for default behavior </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendMPRS(Client client, String fileName, int bufferSize, int flags) throws java.io.IOException
		public static void sendMPRS(Client client, string fileName, int bufferSize, int flags)
		{

			ByteBuffer rawBuf = allocBuffer(3 * 4 + fileName.Length * 2);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			buf.putInt(bufferSize);
			buf.putInt(flags);
			buf.putInt(fileName.Length);
			putString(buf, fileName);

			finishChunkPacket(packet, CHUNK_MPRS, buf.position);
			Log.d("ddm-prof", "Sending " + name(CHUNK_MPRS) + " '" + fileName + "', size=" + bufferSize + ", flags=" + flags);
			client.sendAndConsume(packet, mInst);

			// record the filename we asked for.
			client.clientData.pendingMethodProfiling = fileName;

			// send a status query. this ensure that the status is properly updated if for some
			// reason starting the tracing failed.
			sendMPRQ(client);
		}
Example #27
0
		/// <summary>
		/// Send a DDM packet to the client.
		/// 
		/// Ideally, we can do this with a single channel write.  If that doesn't
		/// happen, we have to prevent anybody else from writing to the channel
		/// until this packet completes, so we synchronize on the channel.
		/// 
		/// Another goal is to avoid unnecessary buffer copies, so we write
		/// directly out of the JdwpPacket's ByteBuffer.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: void sendAndConsume(JdwpPacket packet, ChunkHandler replyHandler) throws java.io.IOException
		internal virtual void sendAndConsume(JdwpPacket packet, ChunkHandler replyHandler)
		{

			if (mChan == null)
			{
				// can happen for e.g. THST packets
				Log.v("ddms", "Not sending packet -- client is closed");
				return;
			}

			if (replyHandler != null)
			{
				/*
				 * Add the ID to the list of outstanding requests.  We have to do
				 * this before sending the packet, in case the response comes back
				 * before our thread returns from the packet-send function.
				 */
				addRequestId(packet.id, replyHandler);
			}

			lock (mChan)
			{
				try
				{
					packet.writeAndConsume(mChan);
				}
				catch (IOException ioe)
				{
					removeRequestId(packet.id);
					throw ioe;
				}
			}
		}
Example #28
0
		/// <summary>
		/// Send a THEN (THread notification ENable) request to the client.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendTHEN(Client client, boolean enable) throws java.io.IOException
		public static void sendTHEN(Client client, bool enable)
		{

			ByteBuffer rawBuf = allocBuffer(1);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			if (enable)
			{
				buf.put(1);
			}
			else
			{
				buf.put(0);
			}

			finishChunkPacket(packet, CHUNK_THEN, buf.position);
			Log.d("ddm-thread", "Sending " + name(CHUNK_THEN) + ": " + enable);
			client.sendAndConsume(packet, mInst);
		}
Example #29
0
		/// <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);
		}
Example #30
0
		/// <summary>
		/// An earlier request resulted in a failure.  This is the expected
		/// response to a HELO message when talking to a non-DDM client.
		/// </summary>
		internal virtual void packetFailed(JdwpPacket reply)
		{
			if (mConnState == ST_NEED_DDM_PKT)
			{
				Log.d("ddms", "Marking " + this + " as non-DDM client");
				mConnState = ST_NOT_DDM;
			}
			else if (mConnState != ST_NOT_DDM)
			{
				Log.w("ddms", "WEIRD: got JDWP failure packet on DDM req");
			}
		}
Example #31
0
 /// <summary>
 /// Forward a packet to the client.
 ///
 /// "mClient" will never be null, though it's possible that the channel
 /// in the client has closed and our send attempt will fail.
 ///
 /// Consumes the packet.
 /// </summary>
 internal void forwardPacketToClient(JdwpPacket packet)
 {
     mClient.sendAndConsume(packet);
 }
Example #32
0
		/// <summary>
		/// Forward the packet to the debugger (if still connected to one).
		/// 
		/// Consumes the packet.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: void forwardPacketToDebugger(JdwpPacket packet) throws java.io.IOException
		internal virtual void forwardPacketToDebugger(JdwpPacket packet)
		{

			Debugger dbg = mDebugger;

			if (dbg == null)
			{
				Log.d("ddms", "Discarding packet");
				packet.consume();
			}
			else
			{
				dbg.sendAndConsume(packet);
			}
		}
Example #33
0
		/*
		 * Send a THST request to the specified client.
		 */
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: private static void sendTHST(Client client) throws java.io.IOException
		private static void sendTHST(Client client)
		{
			ByteBuffer rawBuf = allocBuffer(0);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			// nothing much to say

			finishChunkPacket(packet, CHUNK_THST, buf.position);
			Log.d("ddm-thread", "Sending " + name(CHUNK_THST));
			client.sendAndConsume(packet, mInst);
		}
Example #34
0
		/// <summary>
		/// Send a packet to the debugger.
		/// 
		/// Ideally, we can do this with a single channel write.  If that doesn't
		/// happen, we have to prevent anybody else from writing to the channel
		/// until this packet completes, so we synchronize on the channel.
		/// 
		/// Another goal is to avoid unnecessary buffer copies, so we write
		/// directly out of the JdwpPacket's ByteBuffer.
		/// 
		/// We must synchronize on "mChannel" before writing to it.  We want to
		/// coordinate the buffered data with mChannel creation, so this whole
		/// method is synchronized.
		/// </summary>
		/*lock*/
		internal void sendAndConsume(JdwpPacket packet)
		{
			if (mChannel == null)
			{
				/*
				 * Buffer this up so we can send it to the debugger when it
				 * finally does connect.  This is essential because the VM_START
				 * message might be telling the debugger that the VM is
				 * suspended.  The alternative approach would be for us to
				 * capture and interpret VM_START and send it later if we
				 * didn't choose to un-suspend the VM for our own purposes.
				 */
				Log.d("ddms", "Saving packet 0x" + packet.id.toHexString());
				packet.movePacket(mPreDataBuffer);
			}
			else
			{
				packet.writeAndConsume(mChannel);
			}
		}
Example #35
0
        /*
         * Process an incoming DDM packet. If this is a reply to an earlier request,
         * "handler" will be set to the handler responsible for the original
         * request. The spec allows a JDWP message to include multiple DDM chunks.
         */
        private void callHandler(Client client, JdwpPacket packet, ChunkHandler handler)
        {
            // on first DDM packet received, broadcast a "ready" message
            if (!client.ddmSeen())
            {
                broadcast(CLIENT_READY, client);
            }

            ByteBuffer buf = packet.payload;
            int type, length;
            bool reply = true;

            type = buf.getInt();
            length = buf.getInt();

            if (handler == null)
            {
                // not a reply, figure out who wants it
                lock (mHandlerMap)
                {
                    handler = mHandlerMap[type];
                    reply = false;
                }
            }

            if (handler == null)
            {
                Log.w("ddms", "Received unsupported chunk type " + ChunkHandler.name(type) + " (len=" + length + ")");
            }
            else
            {
                Log.d("ddms", "Calling handler for " + ChunkHandler.name(type) + " [" + handler + "] (len=" + length + ")");
                ByteBuffer ibuf = buf.slice();
                ByteBuffer roBuf = ibuf.asReadOnlyBuffer(); // enforce R/O
                roBuf.order = ChunkHandler.CHUNK_ORDER;
                // do the handling of the chunk synchronized on the client list
                // to be sure there's no concurrency issue when we look for HOME
                // in hasApp()
                lock (mClientList)
                {
                    handler.handleChunk(client, type, roBuf, reply, packet.id);
                }
            }
        }
Example #36
0
        /// <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;
        }
Example #37
0
		/// <summary>
		/// 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.
		/// </summary>
		/// <param name="bufferSize"> is the desired buffer size in bytes (8MB is good) </param>
		/// <param name="flags"> see startMethodTracing() docs; use 0 for default behavior </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendMPSS(Client client, int bufferSize, int flags) throws java.io.IOException
		public static void sendMPSS(Client client, int bufferSize, int flags)
		{

			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);
		}
Example #38
0
		/// <summary>
		/// Send an NHGT (Native Thread GeT) request to the client.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendNHGT(Client client) throws java.io.IOException
		public static void sendNHGT(Client client)
		{

			ByteBuffer rawBuf = allocBuffer(0);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			// no data in request message

			finishChunkPacket(packet, CHUNK_NHGT, buf.position);
			Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHGT));
			client.sendAndConsume(packet, mInst);

			rawBuf = allocBuffer(2);
			packet = new JdwpPacket(rawBuf);
			buf = getChunkDataBuf(rawBuf);

			buf.put(HandleHeap.WHEN_DISABLE);
			buf.put(HandleHeap.WHAT_OBJ);

			finishChunkPacket(packet, CHUNK_NHSG, buf.position);
			Log.d("ddm-nativeheap", "Sending " + name(CHUNK_NHSG));
			client.sendAndConsume(packet, mInst);
		}
Example #39
0
		/// <summary>
		/// Sends an HPSG (HeaP SeGment) request to the client.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendHPSG(Client client, int when, int what) throws java.io.IOException
		public static void sendHPSG(Client client, int when, int what)
		{

			ByteBuffer rawBuf = allocBuffer(2);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			buf.put((byte)when);
			buf.put((byte)what);

			finishChunkPacket(packet, CHUNK_HPSG, buf.position);
			Log.d("ddm-heap", "Sending " + name(CHUNK_HPSG) + ": when=" + when + ", what=" + what);
			client.sendAndConsume(packet, mInst);
		}
Example #40
0
        /// <summary>
        /// Send a non-DDM packet to the client.
        ///
        /// Equivalent to sendAndConsume(packet, null).
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: void sendAndConsume(JdwpPacket packet) throws java.io.IOException
        internal virtual void sendAndConsume(JdwpPacket packet)
        {
            sendAndConsume(packet, null);
        }
Example #41
0
		/// <summary>
		/// Sends an HPDU request to the client.
		/// 
		/// We will get an HPDU response when the heap dump has completed.  On
		/// failure we get a generic failure response.
		/// </summary>
		/// <param name="fileName"> name of output file (on device) </param>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendHPDU(Client client, String fileName) throws java.io.IOException
		public static void sendHPDU(Client client, string fileName)
		{
			ByteBuffer rawBuf = allocBuffer(4 + fileName.Length * 2);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			buf.putInt(fileName.Length);
			putString(buf, fileName);

			finishChunkPacket(packet, CHUNK_HPDU, buf.position);
			Log.d("ddm-heap", "Sending " + name(CHUNK_HPDU) + " '" + fileName + "'");
			client.sendAndConsume(packet, mInst);
			client.clientData.pendingHprofDump = fileName;
		}
Example #42
0
		/// <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);
		}
Example #43
0
		/// <summary>
		/// Sends a REAE (REcent Allocation Enable) request to the client.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendREAE(Client client, boolean enable) throws java.io.IOException
		public static void sendREAE(Client client, bool enable)
		{
			ByteBuffer rawBuf = allocBuffer(1);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			buf.put((byte)(enable ? 1 : 0));

			finishChunkPacket(packet, CHUNK_REAE, buf.position);
			Log.d("ddm-heap", "Sending " + name(CHUNK_REAE) + ": " + enable);
			client.sendAndConsume(packet, mInst);
		}
Example #44
0
	    /// <summary>
		/// Forward a packet to the client.
		/// 
		/// "mClient" will never be null, though it's possible that the channel
		/// in the client has closed and our send attempt will fail.
		/// 
		/// Consumes the packet.
		/// </summary>
	    internal void forwardPacketToClient(JdwpPacket packet) 
		{
			mClient.sendAndConsume(packet);
		}
Example #45
0
        /*
         * Something happened. Figure out what.
         */
        private void processClientActivity(SelectionKey key)
        {
            Client client = (Client)key.attachment();

            try
            {
                if (key.readable == false || key.valid == false)
                {
                    Log.d("ddms", "Invalid key from " + client + ". Dropping client.");
                    dropClient(client, true);                     // notify
                    return;
                }

                client.read();

                /*
                 * See if we have a full packet in the buffer. It's possible we have
                 * more than one packet, so we have to loop.
                 */
                JdwpPacket packet = client.jdwpPacket;
                while (packet != null)
                {
                    if (packet.ddmPacket)
                    {
                        // unsolicited DDM request - hand it off
                        Debug.Assert(!packet.reply);
                        callHandler(client, packet, null);
                        packet.consume();
                    }
                    else if (packet.reply && client.isResponseToUs(packet.id) != null)
                    {
                        // reply to earlier DDM request
                        ChunkHandler handler = client.isResponseToUs(packet.id);
                        if (packet.error)
                        {
                            client.packetFailed(packet);
                        }
                        else if (packet.empty)
                        {
                            Log.d("ddms", "Got empty reply for 0x" + packet.id.toHexString() + " from " + client);
                        }
                        else
                        {
                            callHandler(client, packet, handler);
                        }
                        packet.consume();
                        client.removeRequestId(packet.id);
                    }
                    else
                    {
                        Log.v("ddms", "Forwarding client " + (packet.reply ? "reply" : "event") + " 0x" + packet.id.toHexString() + " to " + client.debugger);
                        client.forwardPacketToDebugger(packet);
                    }

                    // find next
                    packet = client.jdwpPacket;
                }
            }
            catch (CancelledKeyException)
            {
                // key was canceled probably due to a disconnected client before we could
                // read stuff coming from the client, so we drop it.
                dropClient(client, true);                 // notify
            }
            catch (IOException)
            {
                // something closed down, no need to print anything. The client is simply dropped.
                dropClient(client, true);                 // notify
            }
            catch (Exception ex)
            {
                Log.e("ddms", ex);

                /* close the client; automatically un-registers from selector */
                dropClient(client, true);                 // notify

                if (ex is OverflowException)
                {
                    Log.w("ddms", "Client data packet exceeded maximum buffer size " + client);
                }
                else
                {
                    // don't know what this is, display it
                    Log.e("ddms", ex);
                }
            }
        }
Example #46
0
		/// <summary>
		/// Send a non-DDM packet to the client.
		/// 
		/// Equivalent to sendAndConsume(packet, null).
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: void sendAndConsume(JdwpPacket packet) throws java.io.IOException
		internal virtual void sendAndConsume(JdwpPacket packet)
		{
			sendAndConsume(packet, null);
		}
Example #47
0
		/// <summary>
		/// Send a STKL (STacK List) request to the client.  The VM will suspend
		/// the target thread, obtain its stack, and return it.  If the thread
		/// is no longer running, a failure result will be returned.
		/// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in .NET:
//ORIGINAL LINE: public static void sendSTKL(Client client, int threadId) throws java.io.IOException
		public static void sendSTKL(Client client, int threadId)
		{
            /*
			if (false)
			{
				Log.d("ddm-thread", "would send STKL " + threadId);
				return;
			}
            */

			ByteBuffer rawBuf = allocBuffer(4);
			JdwpPacket packet = new JdwpPacket(rawBuf);
			ByteBuffer buf = getChunkDataBuf(rawBuf);

			buf.putInt(threadId);

			finishChunkPacket(packet, CHUNK_STKL, buf.position);
			Log.d("ddm-thread", "Sending " + name(CHUNK_STKL) + ": " + threadId);
			client.sendAndConsume(packet, mInst);
		}