aboutsummaryrefslogtreecommitdiffstats
path: root/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java
diff options
context:
space:
mode:
Diffstat (limited to 'ddms/libs/ddmlib/src/com/android/ddmlib/Client.java')
-rw-r--r--ddms/libs/ddmlib/src/com/android/ddmlib/Client.java839
1 files changed, 0 insertions, 839 deletions
diff --git a/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java b/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java
deleted file mode 100644
index 5b03462..0000000
--- a/ddms/libs/ddmlib/src/com/android/ddmlib/Client.java
+++ /dev/null
@@ -1,839 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.ddmlib;
-
-import com.android.ddmlib.ClientData.MethodProfilingStatus;
-import com.android.ddmlib.DebugPortManager.IDebugPortProvider;
-import com.android.ddmlib.AndroidDebugBridge.IClientChangeListener;
-
-import java.io.IOException;
-import java.nio.BufferOverflowException;
-import java.nio.ByteBuffer;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
-import java.nio.channels.SocketChannel;
-import java.util.HashMap;
-
-/**
- * This represents a single client, usually a DAlvik VM process.
- * <p/>This class gives access to basic client information, as well as methods to perform actions
- * on the client.
- * <p/>More detailed information, usually updated in real time, can be access through the
- * {@link ClientData} class. Each <code>Client</code> object has its own <code>ClientData</code>
- * accessed through {@link #getClientData()}.
- */
-public class Client {
-
- private static final int SERVER_PROTOCOL_VERSION = 1;
-
- /** Client change bit mask: application name change */
- public static final int CHANGE_NAME = 0x0001;
- /** Client change bit mask: debugger status change */
- public static final int CHANGE_DEBUGGER_STATUS = 0x0002;
- /** Client change bit mask: debugger port change */
- public static final int CHANGE_PORT = 0x0004;
- /** Client change bit mask: thread update flag change */
- public static final int CHANGE_THREAD_MODE = 0x0008;
- /** Client change bit mask: thread data updated */
- public static final int CHANGE_THREAD_DATA = 0x0010;
- /** Client change bit mask: heap update flag change */
- public static final int CHANGE_HEAP_MODE = 0x0020;
- /** Client change bit mask: head data updated */
- public static final int CHANGE_HEAP_DATA = 0x0040;
- /** Client change bit mask: native heap data updated */
- public static final int CHANGE_NATIVE_HEAP_DATA = 0x0080;
- /** Client change bit mask: thread stack trace updated */
- public static final int CHANGE_THREAD_STACKTRACE = 0x0100;
- /** Client change bit mask: allocation information updated */
- public static final int CHANGE_HEAP_ALLOCATIONS = 0x0200;
- /** Client change bit mask: allocation information updated */
- public static final int CHANGE_HEAP_ALLOCATION_STATUS = 0x0400;
- /** Client change bit mask: allocation information updated */
- public static final int CHANGE_METHOD_PROFILING_STATUS = 0x0800;
-
- /** Client change bit mask: combination of {@link Client#CHANGE_NAME},
- * {@link Client#CHANGE_DEBUGGER_STATUS}, and {@link Client#CHANGE_PORT}.
- */
- public static final int CHANGE_INFO = CHANGE_NAME | CHANGE_DEBUGGER_STATUS | CHANGE_PORT;
-
- private SocketChannel mChan;
-
- // debugger we're associated with, if any
- private Debugger mDebugger;
- private int mDebuggerListenPort;
-
- // list of IDs for requests we have sent to the client
- private HashMap<Integer,ChunkHandler> mOutstandingReqs;
-
- // chunk handlers stash state data in here
- private ClientData mClientData;
-
- // User interface state. Changing the value causes a message to be
- // sent to the client.
- private boolean mThreadUpdateEnabled;
- private boolean mHeapUpdateEnabled;
-
- /*
- * Read/write buffers. We can get large quantities of data from the
- * client, e.g. the response to a "give me the list of all known classes"
- * request from the debugger. Requests from the debugger, and from us,
- * are much smaller.
- *
- * Pass-through debugger traffic is sent without copying. "mWriteBuffer"
- * is only used for data generated within Client.
- */
- private static final int INITIAL_BUF_SIZE = 2*1024;
- private static final int MAX_BUF_SIZE = 200*1024*1024;
- private ByteBuffer mReadBuffer;
-
- private static final int WRITE_BUF_SIZE = 256;
- private ByteBuffer mWriteBuffer;
-
- private Device mDevice;
-
- private int mConnState;
-
- private static final int ST_INIT = 1;
- private static final int ST_NOT_JDWP = 2;
- private static final int ST_AWAIT_SHAKE = 10;
- private static final int ST_NEED_DDM_PKT = 11;
- private static final int ST_NOT_DDM = 12;
- private static final int ST_READY = 13;
- private static final int ST_ERROR = 20;
- private static final int ST_DISCONNECTED = 21;
-
-
- /**
- * Create an object for a new client connection.
- *
- * @param device the device this client belongs to
- * @param chan the connected {@link SocketChannel}.
- * @param pid the client pid.
- */
- Client(Device device, SocketChannel chan, int pid) {
- mDevice = device;
- mChan = chan;
-
- mReadBuffer = ByteBuffer.allocate(INITIAL_BUF_SIZE);
- mWriteBuffer = ByteBuffer.allocate(WRITE_BUF_SIZE);
-
- mOutstandingReqs = new HashMap<Integer,ChunkHandler>();
-
- mConnState = ST_INIT;
-
- mClientData = new ClientData(pid);
-
- mThreadUpdateEnabled = DdmPreferences.getInitialThreadUpdate();
- mHeapUpdateEnabled = DdmPreferences.getInitialHeapUpdate();
- }
-
- /**
- * Returns a string representation of the {@link Client} object.
- */
- @Override
- public String toString() {
- return "[Client pid: " + mClientData.getPid() + "]";
- }
-
- /**
- * Returns the {@link IDevice} on which this Client is running.
- */
- public IDevice getDevice() {
- return mDevice;
- }
-
- /** Returns the {@link Device} on which this Client is running.
- */
- Device getDeviceImpl() {
- return mDevice;
- }
-
- /**
- * Returns the debugger port for this client.
- */
- public int getDebuggerListenPort() {
- return mDebuggerListenPort;
- }
-
- /**
- * Returns <code>true</code> if the client VM is DDM-aware.
- *
- * Calling here is only allowed after the connection has been
- * established.
- */
- public boolean isDdmAware() {
- switch (mConnState) {
- case ST_INIT:
- case ST_NOT_JDWP:
- case ST_AWAIT_SHAKE:
- case ST_NEED_DDM_PKT:
- case ST_NOT_DDM:
- case ST_ERROR:
- case ST_DISCONNECTED:
- return false;
- case ST_READY:
- return true;
- default:
- assert false;
- return false;
- }
- }
-
- /**
- * Returns <code>true</code> if a debugger is currently attached to the client.
- */
- public boolean isDebuggerAttached() {
- return mDebugger.isDebuggerAttached();
- }
-
- /**
- * Return the Debugger object associated with this client.
- */
- Debugger getDebugger() {
- return mDebugger;
- }
-
- /**
- * Returns the {@link ClientData} object containing this client information.
- */
- public ClientData getClientData() {
- return mClientData;
- }
-
- /**
- * Forces the client to execute its garbage collector.
- */
- public void executeGarbageCollector() {
- try {
- HandleHeap.sendHPGC(this);
- } catch (IOException ioe) {
- Log.w("ddms", "Send of HPGC message failed");
- // ignore
- }
- }
-
- /**
- * Makes the VM dump an HPROF file
- */
- public void dumpHprof() {
- boolean canStream = mClientData.hasFeature(ClientData.FEATURE_HPROF_STREAMING);
- try {
- if (canStream) {
- HandleHeap.sendHPDS(this);
- } else {
- String file = "/sdcard/" + mClientData.getClientDescription().replaceAll(
- "\\:.*", "") + ".hprof";
- HandleHeap.sendHPDU(this, file);
- }
- } catch (IOException e) {
- Log.w("ddms", "Send of HPDU message failed");
- // ignore
- }
- }
-
- public void toggleMethodProfiling() {
- boolean canStream = mClientData.hasFeature(ClientData.FEATURE_PROFILING_STREAMING);
- try {
- if (mClientData.getMethodProfilingStatus() == MethodProfilingStatus.ON) {
- if (canStream) {
- HandleProfiling.sendMPSE(this);
- } else {
- HandleProfiling.sendMPRE(this);
- }
- } else {
- int bufferSize = DdmPreferences.getProfilerBufferSizeMb() * 1024 * 1024;
- if (canStream) {
- HandleProfiling.sendMPSS(this, bufferSize, 0 /*flags*/);
- } else {
- String file = "/sdcard/" +
- mClientData.getClientDescription().replaceAll("\\:.*", "") +
- DdmConstants.DOT_TRACE;
- HandleProfiling.sendMPRS(this, file, bufferSize, 0 /*flags*/);
- }
- }
- } catch (IOException e) {
- Log.w("ddms", "Toggle method profiling failed");
- // ignore
- }
- }
-
- /**
- * Sends a request to the VM to send the enable status of the method profiling.
- * This is asynchronous.
- * <p/>The allocation status can be accessed by {@link ClientData#getAllocationStatus()}.
- * The notification that the new status is available will be received through
- * {@link IClientChangeListener#clientChanged(Client, int)} with a <code>changeMask</code>
- * containing the mask {@link #CHANGE_HEAP_ALLOCATION_STATUS}.
- */
- public void requestMethodProfilingStatus() {
- try {
- HandleHeap.sendREAQ(this);
- } catch (IOException e) {
- Log.e("ddmlib", e);
- }
- }
-
-
- /**
- * Enables or disables the thread update.
- * <p/>If <code>true</code> the VM will be able to send thread information. Thread information
- * must be requested with {@link #requestThreadUpdate()}.
- * @param enabled the enable flag.
- */
- public void setThreadUpdateEnabled(boolean enabled) {
- mThreadUpdateEnabled = enabled;
- if (enabled == false) {
- mClientData.clearThreads();
- }
-
- try {
- HandleThread.sendTHEN(this, enabled);
- } catch (IOException ioe) {
- // ignore it here; client will clean up shortly
- ioe.printStackTrace();
- }
-
- update(CHANGE_THREAD_MODE);
- }
-
- /**
- * Returns whether the thread update is enabled.
- */
- public boolean isThreadUpdateEnabled() {
- return mThreadUpdateEnabled;
- }
-
- /**
- * Sends a thread update request. This is asynchronous.
- * <p/>The thread info can be accessed by {@link ClientData#getThreads()}. The notification
- * that the new data is available will be received through
- * {@link IClientChangeListener#clientChanged(Client, int)} with a <code>changeMask</code>
- * containing the mask {@link #CHANGE_THREAD_DATA}.
- */
- public void requestThreadUpdate() {
- HandleThread.requestThreadUpdate(this);
- }
-
- /**
- * Sends a thread stack trace update request. This is asynchronous.
- * <p/>The thread info can be accessed by {@link ClientData#getThreads()} and
- * {@link ThreadInfo#getStackTrace()}.
- * <p/>The notification that the new data is available
- * will be received through {@link IClientChangeListener#clientChanged(Client, int)}
- * with a <code>changeMask</code> containing the mask {@link #CHANGE_THREAD_STACKTRACE}.
- */
- public void requestThreadStackTrace(int threadId) {
- HandleThread.requestThreadStackCallRefresh(this, threadId);
- }
-
- /**
- * Enables or disables the heap update.
- * <p/>If <code>true</code>, any GC will cause the client to send its heap information.
- * <p/>The heap information can be accessed by {@link ClientData#getVmHeapData()}.
- * <p/>The notification that the new data is available
- * will be received through {@link IClientChangeListener#clientChanged(Client, int)}
- * with a <code>changeMask</code> containing the value {@link #CHANGE_HEAP_DATA}.
- * @param enabled the enable flag
- */
- public void setHeapUpdateEnabled(boolean enabled) {
- mHeapUpdateEnabled = enabled;
-
- try {
- HandleHeap.sendHPIF(this,
- enabled ? HandleHeap.HPIF_WHEN_EVERY_GC : HandleHeap.HPIF_WHEN_NEVER);
-
- HandleHeap.sendHPSG(this,
- enabled ? HandleHeap.WHEN_GC : HandleHeap.WHEN_DISABLE,
- HandleHeap.WHAT_MERGE);
- } catch (IOException ioe) {
- // ignore it here; client will clean up shortly
- }
-
- update(CHANGE_HEAP_MODE);
- }
-
- /**
- * Returns whether the heap update is enabled.
- * @see #setHeapUpdateEnabled(boolean)
- */
- public boolean isHeapUpdateEnabled() {
- return mHeapUpdateEnabled;
- }
-
- /**
- * Sends a native heap update request. this is asynchronous.
- * <p/>The native heap info can be accessed by {@link ClientData#getNativeAllocationList()}.
- * The notification that the new data is available will be received through
- * {@link IClientChangeListener#clientChanged(Client, int)} with a <code>changeMask</code>
- * containing the mask {@link #CHANGE_NATIVE_HEAP_DATA}.
- */
- public boolean requestNativeHeapInformation() {
- try {
- HandleNativeHeap.sendNHGT(this);
- return true;
- } catch (IOException e) {
- Log.e("ddmlib", e);
- }
-
- return false;
- }
-
- /**
- * Enables or disables the Allocation tracker for this client.
- * <p/>If enabled, the VM will start tracking allocation informations. A call to
- * {@link #requestAllocationDetails()} will make the VM sends the information about all the
- * allocations that happened between the enabling and the request.
- * @param enable
- * @see #requestAllocationDetails()
- */
- public void enableAllocationTracker(boolean enable) {
- try {
- HandleHeap.sendREAE(this, enable);
- } catch (IOException e) {
- Log.e("ddmlib", e);
- }
- }
-
- /**
- * Sends a request to the VM to send the enable status of the allocation tracking.
- * This is asynchronous.
- * <p/>The allocation status can be accessed by {@link ClientData#getAllocationStatus()}.
- * The notification that the new status is available will be received through
- * {@link IClientChangeListener#clientChanged(Client, int)} with a <code>changeMask</code>
- * containing the mask {@link #CHANGE_HEAP_ALLOCATION_STATUS}.
- */
- public void requestAllocationStatus() {
- try {
- HandleHeap.sendREAQ(this);
- } catch (IOException e) {
- Log.e("ddmlib", e);
- }
- }
-
- /**
- * Sends a request to the VM to send the information about all the allocations that have
- * happened since the call to {@link #enableAllocationTracker(boolean)} with <var>enable</var>
- * set to <code>null</code>. This is asynchronous.
- * <p/>The allocation information can be accessed by {@link ClientData#getAllocations()}.
- * The notification that the new data is available will be received through
- * {@link IClientChangeListener#clientChanged(Client, int)} with a <code>changeMask</code>
- * containing the mask {@link #CHANGE_HEAP_ALLOCATIONS}.
- */
- public void requestAllocationDetails() {
- try {
- HandleHeap.sendREAL(this);
- } catch (IOException e) {
- Log.e("ddmlib", e);
- }
- }
-
- /**
- * Sends a kill message to the VM.
- */
- public void kill() {
- try {
- HandleExit.sendEXIT(this, 1);
- } catch (IOException ioe) {
- Log.w("ddms", "Send of EXIT message failed");
- // ignore
- }
- }
-
- /**
- * Registers the client with a Selector.
- */
- void register(Selector sel) throws IOException {
- if (mChan != null) {
- mChan.register(sel, SelectionKey.OP_READ, this);
- }
- }
-
- /**
- * Sets the client to accept debugger connection on the "selected debugger port".
- *
- * @see AndroidDebugBridge#setSelectedClient(Client)
- * @see DdmPreferences#setSelectedDebugPort(int)
- */
- public void setAsSelectedClient() {
- MonitorThread monitorThread = MonitorThread.getInstance();
- if (monitorThread != null) {
- monitorThread.setSelectedClient(this);
- }
- }
-
- /**
- * Returns whether this client is the current selected client, accepting debugger connection
- * on the "selected debugger port".
- *
- * @see #setAsSelectedClient()
- * @see AndroidDebugBridge#setSelectedClient(Client)
- * @see DdmPreferences#setSelectedDebugPort(int)
- */
- public boolean isSelectedClient() {
- MonitorThread monitorThread = MonitorThread.getInstance();
- if (monitorThread != null) {
- return monitorThread.getSelectedClient() == this;
- }
-
- return false;
- }
-
- /**
- * Tell the client to open a server socket channel and listen for
- * connections on the specified port.
- */
- void listenForDebugger(int listenPort) throws IOException {
- mDebuggerListenPort = listenPort;
- mDebugger = new Debugger(this, listenPort);
- }
-
- /**
- * Initiate the JDWP handshake.
- *
- * On failure, closes the socket and returns false.
- */
- boolean sendHandshake() {
- 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.getMessage());
- mConnState = ST_ERROR;
- close(true /* notify */);
- return false;
- }
- finally {
- mWriteBuffer.clear();
- }
-
- mConnState = ST_AWAIT_SHAKE;
-
- return true;
- }
-
-
- /**
- * Send a non-DDM packet to the client.
- *
- * Equivalent to sendAndConsume(packet, null).
- */
- void sendAndConsume(JdwpPacket packet) throws IOException {
- sendAndConsume(packet, null);
- }
-
- /**
- * 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.
- */
- void sendAndConsume(JdwpPacket packet, ChunkHandler replyHandler)
- throws IOException {
-
- 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.getId(), replyHandler);
- }
-
- synchronized (mChan) {
- try {
- packet.writeAndConsume(mChan);
- }
- catch (IOException ioe) {
- removeRequestId(packet.getId());
- throw ioe;
- }
- }
- }
-
- /**
- * Forward the packet to the debugger (if still connected to one).
- *
- * Consumes the packet.
- */
- void forwardPacketToDebugger(JdwpPacket packet)
- throws IOException {
-
- Debugger dbg = mDebugger;
-
- if (dbg == null) {
- Log.d("ddms", "Discarding packet");
- packet.consume();
- } else {
- dbg.sendAndConsume(packet);
- }
- }
-
- /**
- * Read data from our channel.
- *
- * This is called when data is known to be available, and we don't yet
- * have a full packet in the buffer. If the buffer is at capacity,
- * expand it.
- */
- void read()
- throws IOException, BufferOverflowException {
-
- int count;
-
- if (mReadBuffer.position() == mReadBuffer.capacity()) {
- if (mReadBuffer.capacity() * 2 > MAX_BUF_SIZE) {
- Log.e("ddms", "Exceeded MAX_BUF_SIZE!");
- throw new BufferOverflowException();
- }
- Log.d("ddms", "Expanding read buffer to "
- + mReadBuffer.capacity() * 2);
-
- ByteBuffer newBuffer = ByteBuffer.allocate(mReadBuffer.capacity() * 2);
-
- // copy entire buffer to new buffer
- mReadBuffer.position(0);
- newBuffer.put(mReadBuffer); // leaves "position" at end of copied
-
- mReadBuffer = newBuffer;
- }
-
- count = mChan.read(mReadBuffer);
- if (count < 0)
- throw new IOException("read failed");
-
- if (Log.Config.LOGV) Log.v("ddms", "Read " + count + " bytes from " + this);
- //Log.hexDump("ddms", Log.DEBUG, mReadBuffer.array(),
- // mReadBuffer.arrayOffset(), mReadBuffer.position());
- }
-
- /**
- * Return information for the first full JDWP packet in the buffer.
- *
- * If we don't yet have a full packet, return null.
- *
- * If we haven't yet received the JDWP handshake, we watch for it here
- * and consume it without admitting to have done so. Upon receipt
- * we send out the "HELO" message, which is why this can throw an
- * IOException.
- */
- JdwpPacket getJdwpPacket() throws IOException {
-
- /*
- * On entry, the data starts at offset 0 and ends at "position".
- * "limit" is set to the buffer capacity.
- */
- if (mConnState == ST_AWAIT_SHAKE) {
- /*
- * The first thing we get from the client is a response to our
- * handshake. It doesn't look like a packet, so we have to
- * handle it specially.
- */
- int result;
-
- result = JdwpPacket.findHandshake(mReadBuffer);
- //Log.v("ddms", "findHand: " + result);
- switch (result) {
- case JdwpPacket.HANDSHAKE_GOOD:
- Log.d("ddms",
- "Good handshake from client, sending HELO to " + mClientData.getPid());
- JdwpPacket.consumeHandshake(mReadBuffer);
- mConnState = ST_NEED_DDM_PKT;
- HandleHello.sendHelloCommands(this, SERVER_PROTOCOL_VERSION);
- // see if we have another packet in the buffer
- return getJdwpPacket();
- case JdwpPacket.HANDSHAKE_BAD:
- Log.d("ddms", "Bad handshake from client");
- if (MonitorThread.getInstance().getRetryOnBadHandshake()) {
- // we should drop the client, but also attempt to reopen it.
- // This is done by the DeviceMonitor.
- mDevice.getMonitor().addClientToDropAndReopen(this,
- IDebugPortProvider.NO_STATIC_PORT);
- } else {
- // mark it as bad, close the socket, and don't retry
- mConnState = ST_NOT_JDWP;
- close(true /* notify */);
- }
- break;
- case JdwpPacket.HANDSHAKE_NOTYET:
- Log.d("ddms", "No handshake from client yet.");
- break;
- default:
- Log.e("ddms", "Unknown packet while waiting for client handshake");
- }
- return null;
- } else if (mConnState == ST_NEED_DDM_PKT ||
- mConnState == ST_NOT_DDM ||
- mConnState == ST_READY) {
- /*
- * Normal packet traffic.
- */
- if (mReadBuffer.position() != 0) {
- if (Log.Config.LOGV) Log.v("ddms",
- "Checking " + mReadBuffer.position() + " bytes");
- }
- return JdwpPacket.findPacket(mReadBuffer);
- } else {
- /*
- * Not expecting data when in this state.
- */
- Log.e("ddms", "Receiving data in state = " + mConnState);
- }
-
- return null;
- }
-
- /*
- * Add the specified ID to the list of request IDs for which we await
- * a response.
- */
- private void addRequestId(int id, ChunkHandler handler) {
- synchronized (mOutstandingReqs) {
- if (Log.Config.LOGV) Log.v("ddms",
- "Adding req 0x" + Integer.toHexString(id) +" to set");
- mOutstandingReqs.put(id, handler);
- }
- }
-
- /*
- * Remove the specified ID from the list, if present.
- */
- void removeRequestId(int id) {
- synchronized (mOutstandingReqs) {
- if (Log.Config.LOGV) Log.v("ddms",
- "Removing req 0x" + Integer.toHexString(id) + " from set");
- mOutstandingReqs.remove(id);
- }
-
- //Log.w("ddms", "Request " + Integer.toHexString(id)
- // + " could not be removed from " + this);
- }
-
- /**
- * Determine whether this is a response to a request we sent earlier.
- * If so, return the ChunkHandler responsible.
- */
- ChunkHandler isResponseToUs(int id) {
-
- synchronized (mOutstandingReqs) {
- ChunkHandler handler = mOutstandingReqs.get(id);
- if (handler != null) {
- if (Log.Config.LOGV) Log.v("ddms",
- "Found 0x" + Integer.toHexString(id)
- + " in request set - " + handler);
- return handler;
- }
- }
-
- return null;
- }
-
- /**
- * An earlier request resulted in a failure. This is the expected
- * response to a HELO message when talking to a non-DDM client.
- */
- 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");
- }
- }
-
- /**
- * The MonitorThread calls this when it sees a DDM request or reply.
- * If we haven't seen a DDM packet before, we advance the state to
- * ST_READY and return "false". Otherwise, just return true.
- *
- * The idea is to let the MonitorThread know when we first see a DDM
- * packet, so we can send a broadcast to the handlers when a client
- * connection is made. This method is synchronized so that we only
- * send the broadcast once.
- */
- synchronized boolean ddmSeen() {
- if (mConnState == ST_NEED_DDM_PKT) {
- mConnState = ST_READY;
- return false;
- } else if (mConnState != ST_READY) {
- Log.w("ddms", "WEIRD: in ddmSeen with state=" + mConnState);
- }
- return true;
- }
-
- /**
- * Close the client socket channel. If there is a debugger associated
- * with us, close that too.
- *
- * Closing a channel automatically unregisters it from the selector.
- * However, we have to iterate through the selector loop before it
- * actually lets them go and allows the file descriptors to close.
- * The caller is expected to manage that.
- * @param notify Whether or not to notify the listeners of a change.
- */
- void close(boolean notify) {
- Log.d("ddms", "Closing " + this.toString());
-
- mOutstandingReqs.clear();
-
- try {
- if (mChan != null) {
- mChan.close();
- mChan = null;
- }
-
- if (mDebugger != null) {
- mDebugger.close();
- mDebugger = null;
- }
- }
- catch (IOException ioe) {
- Log.w("ddms", "failed to close " + this);
- // swallow it -- not much else to do
- }
-
- mDevice.removeClient(this, notify);
- }
-
- /**
- * Returns whether this {@link Client} has a valid connection to the application VM.
- */
- public boolean isValid() {
- return mChan != null;
- }
-
- void update(int changeMask) {
- mDevice.update(this, changeMask);
- }
-}
-