Methods Summary |
---|
void | consume()Consume the JDWP packet.
On entry and exit, "position" is the #of bytes in the buffer.
//Log.d("ddms", "consuming " + mLength + " bytes");
//Log.d("ddms", " posn=" + mBuffer.position()
// + ", limit=" + mBuffer.limit());
/*
* The "flip" call sets "limit" equal to the position (usually the
* end of data) and "position" equal to zero.
*
* compact() copies everything from "position" and "limit" to the
* start of the buffer, sets "position" to the end of data, and
* sets "limit" to the capacity.
*
* On entry, "position" is set to the amount of data in the buffer
* and "limit" is set to the capacity. We want to call flip()
* so that position..limit spans our data, advance "position" past
* the current packet, then compact.
*/
mBuffer.flip(); // limit<-posn, posn<-0
mBuffer.position(mLength);
mBuffer.compact(); // shift posn...limit, posn<-pending data
mLength = 0;
//Log.d("ddms", " after compact, posn=" + mBuffer.position()
// + ", limit=" + mBuffer.limit());
|
static void | consumeHandshake(java.nio.ByteBuffer buf)Remove the handshake string from the buffer.
On entry and exit, "position" is the #of bytes in the buffer.
// 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
|
static int | findHandshake(java.nio.ByteBuffer buf)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
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;
|
static com.android.ddmlib.JdwpPacket | findPacket(java.nio.ByteBuffer buf)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.
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;
|
void | finishPacket(int payloadLength)Finish a packet created with newPacket().
This always creates a command packet, with the next serial number
in sequence.
We have to take "payloadLength" as an argument because we can't
see the position in the "slice" returned by getPayload(). We could
fish it out of the chunk header, but it's legal for there to be
more than one chunk in a JDWP packet.
On exit, "position" points to the end of the data.
assert mIsNew;
ByteOrder oldOrder = mBuffer.order();
mBuffer.order(ChunkHandler.CHUNK_ORDER);
mLength = JDWP_HEADER_LEN + payloadLength;
mId = getNextSerial();
mFlags = 0;
mCmdSet = DDMS_CMD_SET;
mCmd = DDMS_CMD;
mBuffer.putInt(0x00, mLength);
mBuffer.putInt(0x04, mId);
mBuffer.put(0x08, (byte) mFlags);
mBuffer.put(0x09, (byte) mCmdSet);
mBuffer.put(0x0a, (byte) mCmd);
mBuffer.order(oldOrder);
mBuffer.position(mLength);
|
int | getId()Return the packet's ID. For a reply packet, this allows us to
match the reply with the original request.
return mId;
|
int | getLength()Return the length of a packet. This includes the header, so an
empty packet is 11 bytes long.
return mLength;
|
private static synchronized int | getNextSerial()Get the next serial number. This creates a unique serial number
across all connections, not just for the current connection. This
is a useful property when debugging, but isn't necessary.
We can't synchronize on an int, so we use a sync method.
return mSerialId++;
|
java.nio.ByteBuffer | getPayload()Return a slice of the byte buffer, positioned past the JDWP header
to the start of the chunk header. The buffer's limit will be set
to the size of the payload if the size is known; if this is a
packet under construction the limit will be set to the end of the
buffer.
Doesn't examine the packet at all -- works on empty buffers.
ByteBuffer buf;
int oldPosn = mBuffer.position();
mBuffer.position(JDWP_HEADER_LEN);
buf = mBuffer.slice(); // goes from position to limit
mBuffer.position(oldPosn);
if (mLength > 0)
buf.limit(mLength - JDWP_HEADER_LEN);
else
assert mIsNew;
buf.order(ChunkHandler.CHUNK_ORDER);
return buf;
|
boolean | isDdmPacket()Returns "true" if this JDWP packet has a JDWP command type.
This never returns "true" for reply packets.
return (mFlags & REPLY_PACKET) == 0 &&
mCmdSet == DDMS_CMD_SET &&
mCmd == DDMS_CMD;
|
boolean | isEmpty()Returns "true" if this JDWP packet has no data.
return (mLength == JDWP_HEADER_LEN);
|
boolean | isError()Returns "true" if this JDWP packet is a reply with a nonzero
error code.
return isReply() && mErrCode != 0;
|
boolean | isReply()Returns "true" if this JDWP packet is tagged as a reply.
return (mFlags & REPLY_PACKET) != 0;
|
void | movePacket(java.nio.ByteBuffer buf)"Move" the packet data out of the buffer we're sitting on and into
buf at the current position.
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
|
static void | putHandshake(java.nio.ByteBuffer buf)Copy the handshake string into the output buffer.
On exit, "buf"s position will be advanced.
buf.put(mHandshake);
|
void | writeAndConsume(java.nio.channels.SocketChannel chan)Write our packet to "chan". Consumes the packet as part of the
write.
The JDWP packet starts at offset 0 and ends at mBuffer.position().
int oldLimit;
//Log.i("ddms", "writeAndConsume: pos=" + mBuffer.position()
// + ", limit=" + mBuffer.limit());
assert mLength > 0;
mBuffer.flip(); // limit<-posn, posn<-0
oldLimit = mBuffer.limit();
mBuffer.limit(mLength);
while (mBuffer.position() != mBuffer.limit()) {
chan.write(mBuffer);
}
// position should now be at end of packet
assert mBuffer.position() == mLength;
mBuffer.limit(oldLimit);
mBuffer.compact(); // shift posn...limit, posn<-pending data
//Log.i("ddms", " : pos=" + mBuffer.position()
// + ", limit=" + mBuffer.limit());
|