1*055d4590SKeyi Gui<HTML> 2*055d4590SKeyi Gui 3*055d4590SKeyi Gui 4*055d4590SKeyi Gui<head> 5*055d4590SKeyi Gui <title>Dalvik VM Debug Monitor</title> 6*055d4590SKeyi Gui <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 7*055d4590SKeyi Gui <link href="http://www.google.com/favicon.ico" type="image/x-icon" 8*055d4590SKeyi Gui rel="shortcut icon"> 9*055d4590SKeyi Gui <link href="../android.css" type="text/css" rel="stylesheet"> 10*055d4590SKeyi Gui <script language="JavaScript1.2" type="text/javascript"> 11*055d4590SKeyi Guifunction highlight(name) { 12*055d4590SKeyi Gui if (document.getElementById) { 13*055d4590SKeyi Gui tags = [ 'span', 'div', 'tr', 'td' ]; 14*055d4590SKeyi Gui for (i in tags) { 15*055d4590SKeyi Gui elements = document.getElementsByTagName(tags[i]); 16*055d4590SKeyi Gui if (elements) { 17*055d4590SKeyi Gui for (j = 0; j < elements.length; j++) { 18*055d4590SKeyi Gui elementName = elements[j].getAttribute("id"); 19*055d4590SKeyi Gui if (elementName == name) { 20*055d4590SKeyi Gui elements[j].style.backgroundColor = "#C0F0C0"; 21*055d4590SKeyi Gui } else if (elementName && elementName.indexOf("rev") == 0) { 22*055d4590SKeyi Gui elements[j].style.backgroundColor = "#FFFFFF"; 23*055d4590SKeyi Gui } 24*055d4590SKeyi Gui } 25*055d4590SKeyi Gui } 26*055d4590SKeyi Gui } 27*055d4590SKeyi Gui } 28*055d4590SKeyi Gui} 29*055d4590SKeyi Gui </script> 30*055d4590SKeyi Gui</head> 31*055d4590SKeyi Gui<body onload="prettyPrint()"> 32*055d4590SKeyi Gui 33*055d4590SKeyi Gui<h1><a name="My_Project_"></a>Dalvik VM<br>Debug Monitor</h1> 34*055d4590SKeyi Gui 35*055d4590SKeyi Gui<!-- Status is one of: Draft, Current, Needs Update, Obsolete --> 36*055d4590SKeyi Gui<p style="text-align:center"><strong>Status:</strong><em>Draft</em> 37*055d4590SKeyi Gui<small>(as of March 6, 2007)</small></p> 38*055d4590SKeyi Gui<address> 39*055d4590SKeyi Gui[authors] 40*055d4590SKeyi Gui</address> 41*055d4590SKeyi Gui 42*055d4590SKeyi Gui<!-- last modified date can be different to the "Status date." It automatically 43*055d4590SKeyi Guiupdates 44*055d4590SKeyi Guiwhenever the file is modified. --> 45*055d4590SKeyi Gui<i>Modified:</i> 46*055d4590SKeyi Gui <!-- this script automatically sets the modified date,you don't need to modify 47*055d4590SKeyi Guiit --> 48*055d4590SKeyi Gui <script type=text/javascript> 49*055d4590SKeyi Gui <!-- 50*055d4590SKeyi Gui var lm = new Date(document.lastModified); 51*055d4590SKeyi Gui document.write(lm.toDateString()); 52*055d4590SKeyi Gui //--> 53*055d4590SKeyi Gui </script> 54*055d4590SKeyi Gui</address> 55*055d4590SKeyi Gui 56*055d4590SKeyi Gui<p><br> 57*055d4590SKeyi Gui<HR> 58*055d4590SKeyi Gui 59*055d4590SKeyi Gui<h2>Introduction</h2> 60*055d4590SKeyi Gui 61*055d4590SKeyi Gui<p>It's extremely useful to be able to monitor the live state of the 62*055d4590SKeyi GuiVM. For Android, we need to monitor multiple VMs running on a device 63*055d4590SKeyi Guiconnected through USB or a wireless network connection. This document 64*055d4590SKeyi Guidescribes a debug monitor server that interacts with multiple VMs, and 65*055d4590SKeyi Guian API that VMs and applications can use to provide information 66*055d4590SKeyi Guito the monitor. 67*055d4590SKeyi Gui 68*055d4590SKeyi Gui<p>Some things we can monitor with the Dalvik Debug Monitor ("DDM"): 69*055d4590SKeyi Gui<ul> 70*055d4590SKeyi Gui <li> Thread states. Track thread creation/exit, busy/idle status. 71*055d4590SKeyi Gui <li> Overall heap status, useful for a heap bitmap display or 72*055d4590SKeyi Gui fragmentation analysis. 73*055d4590SKeyi Gui</ul> 74*055d4590SKeyi Gui 75*055d4590SKeyi Gui<p>It is possible for something other than a VM to act as a DDM client, but 76*055d4590SKeyi Guithat is a secondary goal. Examples include "logcat" log extraction 77*055d4590SKeyi Guiand system monitors for virtual memory usage and load average. 78*055d4590SKeyi Gui 79*055d4590SKeyi Gui<p>It's also possible for the DDM server to be run on the device, with 80*055d4590SKeyi Guithe information presented through the device UI. However, the initial goal 81*055d4590SKeyi Guiis to provide a display tool that takes advantage of desktop tools and 82*055d4590SKeyi Guiscreen real estate. 83*055d4590SKeyi Gui 84*055d4590SKeyi Gui<p>This work is necessary because we are unable to use standard JVMTI-based 85*055d4590SKeyi Guitools with Dalvik. JVMTI relies on bytecode insertion, which is not 86*055d4590SKeyi Guicurrently possible because Dalvik doesn't support Java bytecode. 87*055d4590SKeyi Gui 88*055d4590SKeyi Gui<p>The DDM server is written in the Java programming language 89*055d4590SKeyi Guifor portability. It uses a desktop 90*055d4590SKeyi GuiUI toolkit (SWT) for its interface. 91*055d4590SKeyi Gui 92*055d4590SKeyi Gui 93*055d4590SKeyi Gui<h2>Protocol</h2> 94*055d4590SKeyi Gui 95*055d4590SKeyi Gui<p>To take advantage of existing infrastructure we are piggy-backing the 96*055d4590SKeyi GuiDDM protocol on top of JDWP (the Java Debug Wire Protocol, normally spoken 97*055d4590SKeyi Guibetween a VM and a debugger). To a 98*055d4590SKeyi Guinon-DDM client, the DDM server just looks like a debugger. 99*055d4590SKeyi Gui 100*055d4590SKeyi Gui<p>The JDWP protocol is very close to what we want to use. In particular: 101*055d4590SKeyi Gui<ul> 102*055d4590SKeyi Gui <li>It explicitly allows for vendor-defined packets, so there is no 103*055d4590SKeyi Gui need to "bend" the JDWP spec. 104*055d4590SKeyi Gui <li>Events may be posted from the VM at arbitrary points. Such 105*055d4590SKeyi Gui events do not elicit a response from the debugger, meaning the client 106*055d4590SKeyi Gui can post data and immediately resume work without worrying about the 107*055d4590SKeyi Gui eventual response. 108*055d4590SKeyi Gui <li>The basic protocol is stateless and asynchronous. Request packets 109*055d4590SKeyi Gui from the debugger side include a serial number, which the VM includes 110*055d4590SKeyi Gui in the response packet. This allows multiple simultaneous 111*055d4590SKeyi Gui conversations, which means the DDM traffic can be interleaved with 112*055d4590SKeyi Gui debugger traffic. 113*055d4590SKeyi Gui</ul> 114*055d4590SKeyi Gui 115*055d4590SKeyi Gui<p>There are a few issues with using JDWP for our purposes: 116*055d4590SKeyi Gui<ul> 117*055d4590SKeyi Gui <li>The VM only expects one connection from a debugger, so you couldn't 118*055d4590SKeyi Gui attach the monitor and a debugger at the same time. This will be 119*055d4590SKeyi Gui worked around by connecting the debugger to the monitor and passing the 120*055d4590SKeyi Gui traffic through. (We're already doing the pass-through with "jdwpspy"; 121*055d4590SKeyi Gui requires some management of our request IDs though.) This should 122*055d4590SKeyi Gui be more convenient than the current "guess the port 123*055d4590SKeyi Gui number" system when we're attached to a device. 124*055d4590SKeyi Gui <li>The VM behaves differently when a debugger is attached. It will 125*055d4590SKeyi Gui run more slowly, and any objects passed to the monitor or debugger are 126*055d4590SKeyi Gui immune to GC. We can work around this by not enabling the slow path 127*055d4590SKeyi Gui until non-DDM traffic is observed. We also want to have a "debugger 128*055d4590SKeyi Gui has connected/disconnected" message that allows the VM to release 129*055d4590SKeyi Gui debugger-related resources without dropping the net connection. 130*055d4590SKeyi Gui <li>Non-DDM VMs should not freak out when DDM connects. There are 131*055d4590SKeyi Gui no guarantees here for 3rd-party VMs (e.g. a certain mainstream VM, 132*055d4590SKeyi Gui which crashes instantly), but our older JamVM can be 133*055d4590SKeyi Gui configured to reject the "hello" packet. 134*055d4590SKeyi Gui</ul> 135*055d4590SKeyi Gui 136*055d4590SKeyi Gui 137*055d4590SKeyi Gui<h3>Connection Establishment</h3> 138*055d4590SKeyi Gui 139*055d4590SKeyi Gui<p>There are two basic approaches: have the server contact the VMs, and 140*055d4590SKeyi Guihave the VMs contact the server. The former is less "precise" than the 141*055d4590SKeyi Guilatter, because you have to scan for the clients, but it has some 142*055d4590SKeyi Guiadvantages. 143*055d4590SKeyi Gui 144*055d4590SKeyi Gui<p>There are three interesting scenarios: 145*055d4590SKeyi Gui<ol> 146*055d4590SKeyi Gui <li>The DDM server is started, then the USB-attached device is booted 147*055d4590SKeyi Gui or the simulator is launched. 148*055d4590SKeyi Gui <li>The device or simulator is already running when the DDM server 149*055d4590SKeyi Gui is started. 150*055d4590SKeyi Gui <li>The DDM server is running when an already-started device is 151*055d4590SKeyi Gui attached to USB. 152*055d4590SKeyi Gui</ol> 153*055d4590SKeyi Gui<p>If we have the VMs connect to the DDM server on startup, we only handle 154*055d4590SKeyi Guicase #1. If the DDM server scans for VMs when it starts, we only handle 155*055d4590SKeyi Guicase #2. Neither handles case #3, which is probably the most important 156*055d4590SKeyi Guiof the bunch as the device matures. 157*055d4590SKeyi Gui<p>The plan is to have a drop-down menu with two entries, 158*055d4590SKeyi Gui"scan workstation" and "scan device". 159*055d4590SKeyi GuiThe former causes the DDM server to search for VMs on "localhost", the 160*055d4590SKeyi Guilatter causes it to search for VMs on the other side of an ADB connection. 161*055d4590SKeyi GuiThe DDM server will scan for VMs every few seconds, either checking a 162*055d4590SKeyi Guirange of known VM ports (e.g. 8000-8040) or interacting with some sort 163*055d4590SKeyi Guiof process database on the device. Changing modes causes all existing 164*055d4590SKeyi Guiconnections to be dropped. 165*055d4590SKeyi Gui<p>When the DDM server first starts, it will try to execute "adb usb" 166*055d4590SKeyi Guito ensure that the ADB server is running. (Note it will be necessary 167*055d4590SKeyi Guito launch the DDM server from a shell with "adb" in the path.) If this 168*055d4590SKeyi Guifails, talking to the device will still be possible so long as the ADB 169*055d4590SKeyi Guidaemon is already running. 170*055d4590SKeyi Gui 171*055d4590SKeyi Gui<h4>Connecting a Debugger</h4> 172*055d4590SKeyi Gui 173*055d4590SKeyi Gui<p>With the DDM server sitting on the JDWP port of all VMs, it will be 174*055d4590SKeyi Guinecessary to connect the debugger through the DDM server. Each VM being 175*055d4590SKeyi Guidebugged will have a separate port being listened to by the DDM server, 176*055d4590SKeyi Guiallowing you to connect a debugger to one or more VMs simultaneously. 177*055d4590SKeyi Gui 178*055d4590SKeyi Gui<p>In the common case, however, the developer will only want to debug 179*055d4590SKeyi Guia single VM. One port (say 8700) will be listened to by the DDM server, 180*055d4590SKeyi Guiand anything connecting to it will be connected to the "current VM" 181*055d4590SKeyi Gui(selected in the UI). This should allow developers to focus on a 182*055d4590SKeyi Guisingle application, which may otherwise shift around in the ordering, without 183*055d4590SKeyi Guihaving to adjust their IDE settings to a different port every time they 184*055d4590SKeyi Guirestart the device. 185*055d4590SKeyi Gui 186*055d4590SKeyi Gui 187*055d4590SKeyi Gui<h3>Packet Format</h3> 188*055d4590SKeyi Gui 189*055d4590SKeyi Gui<p>Information is sent in chunks. Each chunk starts with: 190*055d4590SKeyi Gui<pre> 191*055d4590SKeyi Guiu4 type 192*055d4590SKeyi Guiu4 length 193*055d4590SKeyi Gui</pre> 194*055d4590SKeyi Guiand contains a variable amount of type-specific data. 195*055d4590SKeyi GuiUnrecognized types cause an empty response from the client and 196*055d4590SKeyi Guiare quietly ignored by the server. [Should probably return an error; 197*055d4590SKeyi Guineed an "error" chunk type and a handler on the server side.] 198*055d4590SKeyi Gui 199*055d4590SKeyi Gui<p>The same chunk type may have different meanings when sent in different 200*055d4590SKeyi Guidirections. For example, the same type may be used for both a query and 201*055d4590SKeyi Guia response to the query. The same type must always be used in 202*055d4590SKeyi Guirelated transactions. 203*055d4590SKeyi Gui 204*055d4590SKeyi Gui<p>This is somewhat redundant with the JDWP framing, which includes a 205*055d4590SKeyi Gui4-byte length and a two-byte type code ("command set" and "command"; a 206*055d4590SKeyi Guirange of command set values is designated for "vendor-defined commands 207*055d4590SKeyi Guiand extensions"). Using the chunk format allows us to remain independent 208*055d4590SKeyi Guiof the underlying transport, avoids intrusive integration 209*055d4590SKeyi Guiwith JDWP client code, and provides a way to send multiple chunks in a 210*055d4590SKeyi Guisingle transmission unit. [I'm taking the multi-chunk packets into 211*055d4590SKeyi Guiaccount in the design, but do not plan to implement them unless the need 212*055d4590SKeyi Guiarises.] 213*055d4590SKeyi Gui 214*055d4590SKeyi Gui<p>Because we may be sending data over a slow USB link, the chunks may be 215*055d4590SKeyi Guicompressed. Compressed chunks are written as a chunk type that 216*055d4590SKeyi Guiindicates the compression, followed by the compressed length, followed 217*055d4590SKeyi Guiby the original chunk type and the uncompressed length. For zlib's deflate 218*055d4590SKeyi Guialgorithm, the chunk type is "ZLIB". 219*055d4590SKeyi Gui 220*055d4590SKeyi Gui<p>Following the JDWP model, packets sent from the server to the client 221*055d4590SKeyi Guiare always acknowledged, but packets sent from client to server never are. 222*055d4590SKeyi GuiThe JDWP error code field is always set to "no error"; failure responses 223*055d4590SKeyi Guifrom specific requests must be encoded into the DDM messages. 224*055d4590SKeyi Gui 225*055d4590SKeyi Gui<p>In what follows "u4" is an unsigned 32-bit value and "u1" is an 226*055d4590SKeyi Guiunsigned 8-bit value. Values are written in big-endian order to match 227*055d4590SKeyi GuiJDWP. 228*055d4590SKeyi Gui 229*055d4590SKeyi Gui 230*055d4590SKeyi Gui<h3>Initial Handshake</h3> 231*055d4590SKeyi Gui 232*055d4590SKeyi Gui<p>After the JDWP handshake, the server sends a HELO chunk to the client. 233*055d4590SKeyi GuiIf the client's JDWP layer rejects it, the server assumes that the client 234*055d4590SKeyi Guiis not a DDM-aware VM, and does not send it any further DDM queries. 235*055d4590SKeyi Gui<p>On the client side, upon seeing a HELO it can know that a DDM server 236*055d4590SKeyi Guiis attached and prepare accordingly. The VM should not assume that a 237*055d4590SKeyi Guidebugger is attached until a non-DDM packet arrives. 238*055d4590SKeyi Gui 239*055d4590SKeyi Gui<h4>Chunk HELO (server --> client)</h4> 240*055d4590SKeyi Gui<p>Basic "hello" message. 241*055d4590SKeyi Gui<pre> 242*055d4590SKeyi Guiu4 DDM server protocol version 243*055d4590SKeyi Gui</pre> 244*055d4590SKeyi Gui 245*055d4590SKeyi Gui 246*055d4590SKeyi Gui<h4>Chunk HELO (client --> server, reply only)</h4> 247*055d4590SKeyi GuiInformation about the client. Must be sent in response to the HELO message. 248*055d4590SKeyi Gui<pre> 249*055d4590SKeyi Guiu4 DDM client protocol version 250*055d4590SKeyi Guiu4 pid 251*055d4590SKeyi Guiu4 VM ident string len (in 16-bit units) 252*055d4590SKeyi Guiu4 application name len (in 16-bit units) 253*055d4590SKeyi Guivar VM ident string (UTF-16) 254*055d4590SKeyi Guivar application name (UTF-16) 255*055d4590SKeyi Gui</pre> 256*055d4590SKeyi Gui 257*055d4590SKeyi Gui<p>If the client does not wish to speak to the DDM server, it should respond 258*055d4590SKeyi Guiwith a JDWP error packet. This is the same behavior you'd get from a VM 259*055d4590SKeyi Guithat doesn't support DDM. 260*055d4590SKeyi Gui 261*055d4590SKeyi Gui 262*055d4590SKeyi Gui<h3>Debugger Management</h3> 263*055d4590SKeyi Gui<p>VMs usually prepare for debugging when a JDWP connection is established, 264*055d4590SKeyi Guiand release debugger-related resources when the connection drops. We want 265*055d4590SKeyi Guito open the JDWP connection early and hold it open after the debugger 266*055d4590SKeyi Guidisconnects. 267*055d4590SKeyi Gui<p>The VM can tell when a debugger attaches, because it will start seeing 268*055d4590SKeyi Guinon-DDM JDWP traffic, but it can't identify the disconnect. For this reason, 269*055d4590SKeyi Guiwe need to send a packet to the client when the debugger disconnects. 270*055d4590SKeyi Gui<p>If the DDM server is talking to a non-DDM-aware client, it will be 271*055d4590SKeyi Guinecessary to drop and re-establish the connection when the debugger goes away. 272*055d4590SKeyi Gui(This also works with DDM-aware clients; this packet is an optimization.) 273*055d4590SKeyi Gui 274*055d4590SKeyi Gui<h4>Chunk DBGD (server --> client)</h4> 275*055d4590SKeyi Gui<p>Debugger has disconnected. The client responds with a DBGD to acknowledge 276*055d4590SKeyi Guireceipt. No data in request, no response required. 277*055d4590SKeyi Gui 278*055d4590SKeyi Gui 279*055d4590SKeyi Gui<h3>VM Info</h3> 280*055d4590SKeyi Gui<p>Update the server's info about the client. 281*055d4590SKeyi Gui 282*055d4590SKeyi Gui<h4>Chunk APNM (client --> server)</h4> 283*055d4590SKeyi Gui 284*055d4590SKeyi Gui<p>If a VM's application name changes -- possible in our environment because 285*055d4590SKeyi Guiof the "pre-initialized" app processes -- it must send up one of these. 286*055d4590SKeyi Gui<pre> 287*055d4590SKeyi Guiu4 application name len (in 16-bit chars) 288*055d4590SKeyi Guivar application name (UTF-16) 289*055d4590SKeyi Gui</pre> 290*055d4590SKeyi Gui 291*055d4590SKeyi Gui<h4>Chunk WAIT (client --> server)</h4> 292*055d4590SKeyi Gui 293*055d4590SKeyi Gui<p>This tells DDMS that one or more threads are waiting on an external 294*055d4590SKeyi Guievent. The simplest use is to tell DDMS that the VM is waiting for a 295*055d4590SKeyi Guidebugger to attach. 296*055d4590SKeyi Gui<pre> 297*055d4590SKeyi Guiu1 reason (0 = wait for debugger) 298*055d4590SKeyi Gui</pre> 299*055d4590SKeyi GuiIf DDMS is attached, the client VM sends this up when waitForDebugger() 300*055d4590SKeyi Guiis called. If waitForDebugger() is called before DDMS attaches, the WAIT 301*055d4590SKeyi Guichunk will be sent up at about the same time as the HELO response. 302*055d4590SKeyi Gui 303*055d4590SKeyi Gui 304*055d4590SKeyi Gui<h3>Thread Status</h3> 305*055d4590SKeyi Gui 306*055d4590SKeyi Gui<p>The client can send updates when their status changes, or periodically 307*055d4590SKeyi Guisend thread state info, e.g. 2x per 308*055d4590SKeyi Guisecond to allow a "blinkenlights" display of thread activity. 309*055d4590SKeyi Gui 310*055d4590SKeyi Gui<h4>Chunk THEN (server --> client)</h4> 311*055d4590SKeyi Gui 312*055d4590SKeyi Gui<p>Enable thread creation/death notification. 313*055d4590SKeyi Gui<pre> 314*055d4590SKeyi Guiu1 boolean (true=enable, false=disable) 315*055d4590SKeyi Gui</pre> 316*055d4590SKeyi Gui<p>The response is empty. The client generates THCR packets for all 317*055d4590SKeyi Guiknown threads. (Note the THCR packets may arrive before the THEN 318*055d4590SKeyi Guiresponse.) 319*055d4590SKeyi Gui 320*055d4590SKeyi Gui<h4>Chunk THCR (client --> server)</h4> 321*055d4590SKeyi Gui<p>Thread Creation notification. 322*055d4590SKeyi Gui<pre> 323*055d4590SKeyi Guiu4 VM-local thread ID (usually a small int) 324*055d4590SKeyi Guiu4 thread name len (in 16-bit chars) 325*055d4590SKeyi Guivar thread name (UTF-16) 326*055d4590SKeyi Gui</pre> 327*055d4590SKeyi Gui 328*055d4590SKeyi Gui<h4>Chunk THDE (client --> server)</h4> 329*055d4590SKeyi Gui<p>Thread Death notification. 330*055d4590SKeyi Gui<pre> 331*055d4590SKeyi Guiu4 VM-local thread ID 332*055d4590SKeyi Gui</pre> 333*055d4590SKeyi Gui 334*055d4590SKeyi Gui<h4>Chunk THST (server --> client)</h4> 335*055d4590SKeyi Gui 336*055d4590SKeyi Gui<p>Enable periodic thread activity updates. 337*055d4590SKeyi GuiThreads in THCR messages are assumed to be in the "initializing" state. A 338*055d4590SKeyi GuiTHST message should follow closely on the heels of THCR. 339*055d4590SKeyi Gui<pre> 340*055d4590SKeyi Guiu4 interval, in msec 341*055d4590SKeyi Gui</pre> 342*055d4590SKeyi Gui<p>An interval of 0 disables the updates. This is done periodically, 343*055d4590SKeyi Guirather than every time the thread state changes, to reduce the amount 344*055d4590SKeyi Guiof data that must be sent for an actively running VM. 345*055d4590SKeyi Gui 346*055d4590SKeyi Gui<h4>Chunk THST (client --> server)</h4> 347*055d4590SKeyi Gui<p>Thread Status, describing the state of one or more threads. This is 348*055d4590SKeyi Guimost useful when creation/death notifications are enabled first. The 349*055d4590SKeyi Guioverall layout is: 350*055d4590SKeyi Gui<pre> 351*055d4590SKeyi Guiu4 count 352*055d4590SKeyi Guivar thread data 353*055d4590SKeyi Gui</pre> 354*055d4590SKeyi GuiThen, for every thread: 355*055d4590SKeyi Gui<pre> 356*055d4590SKeyi Guiu4 VM-local thread ID 357*055d4590SKeyi Guiu1 thread state 358*055d4590SKeyi Guiu1 suspended 359*055d4590SKeyi Gui</pre> 360*055d4590SKeyi Gui<p>"thread state" must be one of: 361*055d4590SKeyi Gui<ul> <!-- don't use ol, we may need (-1) or sparse --> 362*055d4590SKeyi Gui <li> 1 - running (now executing or ready to do so) 363*055d4590SKeyi Gui <li> 2 - sleeping (in Thread.sleep()) 364*055d4590SKeyi Gui <li> 3 - monitor (blocked on a monitor lock) 365*055d4590SKeyi Gui <li> 4 - waiting (in Object.wait()) 366*055d4590SKeyi Gui <li> 5 - initializing 367*055d4590SKeyi Gui <li> 6 - starting 368*055d4590SKeyi Gui <li> 7 - native (executing native code) 369*055d4590SKeyi Gui <li> 8 - vmwait (waiting on a VM resource) 370*055d4590SKeyi Gui</ul> 371*055d4590SKeyi Gui<p>"suspended" will be 0 if the thread is running, 1 if not. 372*055d4590SKeyi Gui<p>[Any reason not to make "suspended" be the high bit of "thread state"? 373*055d4590SKeyi GuiDo we need to differentiate suspend-by-GC from suspend-by-debugger?] 374*055d4590SKeyi Gui<p>[We might be able to send the currently-executing method. This is a 375*055d4590SKeyi Guilittle risky in a running VM, and increases the size of the messages 376*055d4590SKeyi Guiconsiderably, but might be handy.] 377*055d4590SKeyi Gui 378*055d4590SKeyi Gui 379*055d4590SKeyi Gui<h3>Heap Status</h3> 380*055d4590SKeyi Gui 381*055d4590SKeyi Gui<p>The client sends what amounts to a color-coded bitmap to the server, 382*055d4590SKeyi Guiindicating which stretches of memory are free and which are in use. For 383*055d4590SKeyi Guicompactness the bitmap is run-length encoded, and based on multi-byte 384*055d4590SKeyi Gui"allocation units" rather than byte counts. 385*055d4590SKeyi Gui 386*055d4590SKeyi Gui<p>In the future the server will be able to correlate the bitmap with more 387*055d4590SKeyi Guidetailed object data, so enough information is provided to associate the 388*055d4590SKeyi Guibitmap data with virtual addresses. 389*055d4590SKeyi Gui 390*055d4590SKeyi Gui<p>Heaps may be broken into segments within the VM, and due to memory 391*055d4590SKeyi Guiconstraints it may be desirable to send the bitmap in smaller pieces, 392*055d4590SKeyi Guiso the protocol allows the heap data to be sent in several chunks. 393*055d4590SKeyi GuiTo avoid ambiguity, the client is required 394*055d4590SKeyi Guito send explicit "start" and "end" messages during an update. 395*055d4590SKeyi Gui 396*055d4590SKeyi Gui<p>All messages include a "heap ID" that can be used to differentiate 397*055d4590SKeyi Guibetween multiple independent virtual heaps or perhaps a native heap. The 398*055d4590SKeyi Guiclient is allowed to send information about different heaps simultaneously, 399*055d4590SKeyi Guiso all heap-specific information is tagged with a "heap ID". 400*055d4590SKeyi Gui 401*055d4590SKeyi Gui<h4>Chunk HPIF (server --> client)</h4> 402*055d4590SKeyi Gui<p>Request heap info. 403*055d4590SKeyi Gui<pre> 404*055d4590SKeyi Guiu1 when to send 405*055d4590SKeyi Gui</pre> 406*055d4590SKeyi Gui<p>The "when" values are: 407*055d4590SKeyi Gui<pre> 408*055d4590SKeyi Gui0: never 409*055d4590SKeyi Gui1: immediately 410*055d4590SKeyi Gui2: at the next GC 411*055d4590SKeyi Gui3: at every GC 412*055d4590SKeyi Gui</pre> 413*055d4590SKeyi Gui 414*055d4590SKeyi Gui<h4>Chunk HPIF (client --> server, reply only)</h4> 415*055d4590SKeyi Gui<p>Heap Info. General information about the heap, suitable for a summary 416*055d4590SKeyi Guidisplay. 417*055d4590SKeyi Gui<pre> 418*055d4590SKeyi Guiu4 number of heaps 419*055d4590SKeyi Gui</pre> 420*055d4590SKeyi GuiFor each heap: 421*055d4590SKeyi Gui<pre> 422*055d4590SKeyi Guiu4 heap ID 423*055d4590SKeyi Guiu8 timestamp in ms since Unix epoch 424*055d4590SKeyi Guiu1 capture reason (same as 'when' value from server) 425*055d4590SKeyi Guiu4 max heap size in bytes (-Xmx) 426*055d4590SKeyi Guiu4 current heap size in bytes 427*055d4590SKeyi Guiu4 current number of bytes allocated 428*055d4590SKeyi Guiu4 current number of objects allocated 429*055d4590SKeyi Gui</pre> 430*055d4590SKeyi Gui<p>[We can get some of this from HPSG, more from HPSO.] 431*055d4590SKeyi Gui<p>[Do we need a "heap overhead" stat here, indicating how much goes to 432*055d4590SKeyi Guiwaste? e.g. (8 bytes per object * number of objects)] 433*055d4590SKeyi Gui 434*055d4590SKeyi Gui<h4>Chunk HPSG (server --> client)</h4> 435*055d4590SKeyi Gui<p>Request transmission of heap segment data. 436*055d4590SKeyi Gui<pre> 437*055d4590SKeyi Guiu1 when to send 438*055d4590SKeyi Guiu1 what to send 439*055d4590SKeyi Gui</pre> 440*055d4590SKeyi Gui<p>The "when" to send will be zero to disable transmission, 1 to send 441*055d4590SKeyi Guiduring a GC. Other values are currently undefined. (Could use to pick 442*055d4590SKeyi Guiwhich part of the GC to send it, or cause periodic transmissions.) 443*055d4590SKeyi Gui<p>The "what" field is currently 0 for HPSG and 1 for HPSO. 444*055d4590SKeyi Gui<p>No reply is expected. 445*055d4590SKeyi Gui 446*055d4590SKeyi Gui<h4>Chunk NHSG (server --> client)</h4> 447*055d4590SKeyi Gui<p>Request transmission of native heap segment data. 448*055d4590SKeyi Gui<pre> 449*055d4590SKeyi Guiu1 when to send 450*055d4590SKeyi Guiu1 what to send 451*055d4590SKeyi Gui</pre> 452*055d4590SKeyi Gui<p>The "when" to send will be zero to disable transmission, 1 to send 453*055d4590SKeyi Guiduring a GC. Other values are currently undefined. 454*055d4590SKeyi Gui<p>The "what" field is currently ignored. 455*055d4590SKeyi Gui<p>No reply is expected. 456*055d4590SKeyi Gui 457*055d4590SKeyi Gui<h4>Chunk HPST/NHST (client --> server)</h4> 458*055d4590SKeyi Gui<p>This is a Heap Start message. It tells the server to discard any 459*055d4590SKeyi Guiexisting notion of what the client's heap looks like, and prepare for 460*055d4590SKeyi Guinew information. HPST indicates a virtual heap dump and must be followed 461*055d4590SKeyi Guiby zero or more HPSG/HPSO messages and an HPEN. NHST indicates a native 462*055d4590SKeyi Guiheap dump and must be followed by zero or more NHSG messages and an NHEN. 463*055d4590SKeyi Gui 464*055d4590SKeyi Gui<p>The only data item is: 465*055d4590SKeyi Gui<pre> 466*055d4590SKeyi Guiu4 heap ID 467*055d4590SKeyi Gui</pre> 468*055d4590SKeyi Gui 469*055d4590SKeyi Gui<h4>Chunk HPEN/NHEN (client --> server)</h4> 470*055d4590SKeyi Gui<p>Heap End, indicating that all information about the heap has been sent. 471*055d4590SKeyi GuiA HPST will be paired with an HPEN and an NHST will be paired with an NHEN. 472*055d4590SKeyi Gui 473*055d4590SKeyi Gui<p>The only data item is: 474*055d4590SKeyi Gui<pre> 475*055d4590SKeyi Guiu4 heap ID 476*055d4590SKeyi Gui</pre> 477*055d4590SKeyi Gui 478*055d4590SKeyi Gui<h4>Chunk HPSG (client --> server)</h4> 479*055d4590SKeyi Gui<p>Heap segment data. Each chunk describes all or part of a contiguous 480*055d4590SKeyi Guistretch of heap memory. 481*055d4590SKeyi Gui<pre> 482*055d4590SKeyi Guiu4 heap ID 483*055d4590SKeyi Guiu1 size of allocation unit, in bytes (e.g. 8 bytes) 484*055d4590SKeyi Guiu4 virtual address of segment start 485*055d4590SKeyi Guiu4 offset of this piece (relative to the virtual address) 486*055d4590SKeyi Guiu4 length of piece, in allocation units 487*055d4590SKeyi Guivar usage data 488*055d4590SKeyi Gui</pre> 489*055d4590SKeyi Gui<p>The "usage data" indicates the status of each allocation unit. The data 490*055d4590SKeyi Guiis a stream of pairs of bytes, where the first byte indicates the state 491*055d4590SKeyi Guiof the allocation unit, and the second byte indicates the number of 492*055d4590SKeyi Guiconsecutive allocation units with the same state. 493*055d4590SKeyi Gui<p>The bits in the "state" byte have the following meaning: 494*055d4590SKeyi Gui<pre> 495*055d4590SKeyi Gui+---------------------------------------+ 496*055d4590SKeyi Gui| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | 497*055d4590SKeyi Gui+---------------------------------------+ 498*055d4590SKeyi Gui| P | U0 | K2 | K1 | K0 | S2 | S1 | S0 | 499*055d4590SKeyi Gui+---------------------------------------+ 500*055d4590SKeyi Gui</pre> 501*055d4590SKeyi Gui<ul> 502*055d4590SKeyi Gui <li>'S': solidity 503*055d4590SKeyi Gui <ul> 504*055d4590SKeyi Gui <li>0=free 505*055d4590SKeyi Gui <li>1=has hard reference 506*055d4590SKeyi Gui <li>2=has soft reference 507*055d4590SKeyi Gui <li>3=has weak reference 508*055d4590SKeyi Gui <li>4=has phantom reference 509*055d4590SKeyi Gui <li>5=pending finalization 510*055d4590SKeyi Gui <li>6=marked, about to be swept 511*055d4590SKeyi Gui </ul> 512*055d4590SKeyi Gui <li>'K': kind 513*055d4590SKeyi Gui <ul> 514*055d4590SKeyi Gui <li>0=object 515*055d4590SKeyi Gui <li>1=class object 516*055d4590SKeyi Gui <li>2=array of byte/boolean 517*055d4590SKeyi Gui <li>3=array of char/short 518*055d4590SKeyi Gui <li>4=array of Object/int/float 519*055d4590SKeyi Gui <li>5=array of long/double 520*055d4590SKeyi Gui </ul> 521*055d4590SKeyi Gui <li>'P': partial flag (not used for HPSG) 522*055d4590SKeyi Gui <li>'U': unused, must be zero 523*055d4590SKeyi Gui</ul> 524*055d4590SKeyi Gui 525*055d4590SKeyi Gui<p>The use of the various 'S' types depends on when the information is 526*055d4590SKeyi Guisent. The current plan is to send it either immediately after a GC, 527*055d4590SKeyi Guior between the "mark" and "sweep" phases of the GC. For a fancy generational 528*055d4590SKeyi Guicollector, we may just want to send it up periodically. 529*055d4590SKeyi Gui 530*055d4590SKeyi Gui<p>The run-length byte indicates the number of allocation units minus one, so a 531*055d4590SKeyi Guilength of 255 means there are 256 consecutive units with this state. In 532*055d4590SKeyi Guisome cases, e.g. arrays of bytes, the actual size of the data is rounded 533*055d4590SKeyi Guiup the nearest allocation unit. 534*055d4590SKeyi Gui<p>For HPSG, the runs do not end at object boundaries. It is not possible 535*055d4590SKeyi Guito tell from this bitmap whether a run contains one or several objects. 536*055d4590SKeyi Gui(But see HPSO, below.) 537*055d4590SKeyi Gui<p>[If we find that we have many long runs, we can overload the 'P' flag 538*055d4590SKeyi Guior dedicate the 'U' flag to indicate that we have a 16-bit length instead 539*055d4590SKeyi Guiof 8-bit. We can also use a variable-width integer scheme for the length, 540*055d4590SKeyi Guiencoding 1-128 in one byte, 1-16384 in two bytes, etc.] 541*055d4590SKeyi Gui<p>[Alternate plan for 'K': array of byte, array of char, array of Object, 542*055d4590SKeyi Guiarray of miscellaneous primitive type] 543*055d4590SKeyi Gui<p>To parse the data, the server runs through the usage data until either 544*055d4590SKeyi Gui(a) the end of the chunk is reached, or (b) all allocation units have been 545*055d4590SKeyi Guiaccounted for. (If these two things don't happen at the same time, the 546*055d4590SKeyi Guichunk is rejected.) 547*055d4590SKeyi Gui<p>Example: suppose a VM has a heap at 0x10000 that is 0x2000 bytes long 548*055d4590SKeyi Gui(with an 8-byte allocation unit size, that's 0x0400 units long). 549*055d4590SKeyi GuiThe client could send one chunk (allocSize=8, virtAddr=0x10000, offset=0, 550*055d4590SKeyi Guilength=0x0400) or two (allocSize=8, virtAddr=0x10000, offset=0, length=0x300; 551*055d4590SKeyi Guithen allocSize=8, virtAddr=0x10000, offset=0x300, length=0x100). 552*055d4590SKeyi Gui<p>The client must encode the entire heap, including all free space at 553*055d4590SKeyi Guithe end, or the server will not have an accurate impression of the amount 554*055d4590SKeyi Guiof memory in the heap. This refers to the current heap size, not the 555*055d4590SKeyi Guimaximum heap size. 556*055d4590SKeyi Gui 557*055d4590SKeyi Gui<h4>Chunk HPSO (client --> server)</h4> 558*055d4590SKeyi Gui<p>This is essentially identical to HPSG, but the runs are terminated at 559*055d4590SKeyi Guiobject boundaries. If an object is larger than 256 allocation units, the 560*055d4590SKeyi Gui"partial" flag is set in all runs except the last. 561*055d4590SKeyi Gui<p>The resulting unpacked bitmap is identical, but the object boundary 562*055d4590SKeyi Guiinformation can be used to gain insights into heap layout. 563*055d4590SKeyi Gui<p>[Do we want to have a separate message for this? Maybe just include 564*055d4590SKeyi Guia "variant" flag in the HPST packet. Another possible form of output 565*055d4590SKeyi Guiwould be one that indicates the age, in generations, of each block of 566*055d4590SKeyi Guimemory. That would provide a quick visual indication of "permanent vs. 567*055d4590SKeyi Guitransient residents", perhaps with a 16-level grey scale.] 568*055d4590SKeyi Gui 569*055d4590SKeyi Gui<h4>Chunk NHSG (client --> server)</h4> 570*055d4590SKeyi Gui<p>Native heap segment data. Each chunk describes all or part of a 571*055d4590SKeyi Guicontiguous stretch of native heap memory. The format is the same as 572*055d4590SKeyi Guifor HPSG, except that only solidity values 0 (= free) and 1 (= hard 573*055d4590SKeyi Guireference) are used, and the kind value is always 0 for free chunks 574*055d4590SKeyi Guiand 7 for allocated chunks, indicating a non-VM object. 575*055d4590SKeyi Gui<pre> 576*055d4590SKeyi Guiu4 heap ID 577*055d4590SKeyi Guiu1 size of allocation unit, in bytes (e.g. 8 bytes) 578*055d4590SKeyi Guiu4 virtual address of segment start 579*055d4590SKeyi Guiu4 offset of this piece (relative to the virtual address) 580*055d4590SKeyi Guiu4 length of piece, in allocation units 581*055d4590SKeyi Guivar usage data 582*055d4590SKeyi Gui</pre> 583*055d4590SKeyi Gui 584*055d4590SKeyi Gui<h3>Generic Replies</h3> 585*055d4590SKeyi Gui 586*055d4590SKeyi GuiThe client-side chunk handlers need a common way to report simple success 587*055d4590SKeyi Guior failure. By convention, an empty reply packet indicates success. 588*055d4590SKeyi Gui 589*055d4590SKeyi Gui<h4>Chunk FAIL (client --> server, reply only)</h4> 590*055d4590SKeyi Gui<p>The chunk includes a machine-readable error code and a 591*055d4590SKeyi Guihuman-readable error message. Server code can associate the failure 592*055d4590SKeyi Guiwith the original request by comparing the JDWP packet ID. 593*055d4590SKeyi Gui<p>This allows a standard way of, for example, rejecting badly-formed 594*055d4590SKeyi Guirequest packets. 595*055d4590SKeyi Gui<pre> 596*055d4590SKeyi Guiu4 error code 597*055d4590SKeyi Guiu4 error message len (in 16-bit chars) 598*055d4590SKeyi Guivar error message (UTF-16) 599*055d4590SKeyi Gui</pre> 600*055d4590SKeyi Gui 601*055d4590SKeyi Gui<h3>Miscellaneous</h3> 602*055d4590SKeyi Gui 603*055d4590SKeyi Gui<h4>Chunk EXIT (server --> client)</h4> 604*055d4590SKeyi Gui<p>Cause the client to exit with the specified status, using System.exit(). 605*055d4590SKeyi GuiUseful for certain kinds of testing. 606*055d4590SKeyi Gui<pre> 607*055d4590SKeyi Guiu4 exit status 608*055d4590SKeyi Gui</pre> 609*055d4590SKeyi Gui 610*055d4590SKeyi Gui<h4>Chunk DTRC (server --> client)</h4> 611*055d4590SKeyi Gui<p>[TBD] start/stop dmtrace; can send the results back over the wire. For 612*055d4590SKeyi Guisize reasons we probably need "sending", "data", "key", "finished" as 613*055d4590SKeyi Gui4 separate chunks/packets rather than one glob. 614*055d4590SKeyi Gui 615*055d4590SKeyi Gui 616*055d4590SKeyi Gui<h2>Client API</h2> 617*055d4590SKeyi Gui 618*055d4590SKeyi Gui<p>The API is written in the Java programming language 619*055d4590SKeyi Guifor convenience. The code is free to call native methods if appropriate. 620*055d4590SKeyi Gui 621*055d4590SKeyi Gui<h3>Chunk Handler API</h3> 622*055d4590SKeyi Gui 623*055d4590SKeyi Gui<p>The basic idea is that arbitrary code can register handlers for 624*055d4590SKeyi Guispecific chunk types. When a DDM chunk with that type arrives, the 625*055d4590SKeyi Guiappropriate handler is invoked. The handler's return value provides the 626*055d4590SKeyi Guiresponse to the server. 627*055d4590SKeyi Gui 628*055d4590SKeyi Gui<p>There are two packages. android.ddm lives in the "framework" library, 629*055d4590SKeyi Guiand has all of the chunk handlers and registration code. It can freely 630*055d4590SKeyi Guiuse Android classes. org.apache.harmony.dalvik.ddmc lives in the "core" 631*055d4590SKeyi Guilibrary, and has 632*055d4590SKeyi Guisome base classes and features that interact with the VM. Nothing should 633*055d4590SKeyi Guineed to modify the org.apache.harmony.dalvik.ddmc classes. 634*055d4590SKeyi Gui 635*055d4590SKeyi Gui<p>The DDM classes pass chunks of data around with a simple class: 636*055d4590SKeyi Gui 637*055d4590SKeyi Gui<pre class=prettyprint> 638*055d4590SKeyi Guiclass Chunk { 639*055d4590SKeyi Gui int type; 640*055d4590SKeyi Gui byte[] data; 641*055d4590SKeyi Gui int offset, length; 642*055d4590SKeyi Gui}; 643*055d4590SKeyi Gui</pre> 644*055d4590SKeyi Gui 645*055d4590SKeyi Gui<p>The chunk handlers accept and return them: 646*055d4590SKeyi Gui<pre class=prettyprint> 647*055d4590SKeyi Guipublic Chunk handleChunk(Chunk request) 648*055d4590SKeyi Gui</pre> 649*055d4590SKeyi Gui<p>The code is free to parse the chunk and generate a response in any 650*055d4590SKeyi Guiway it chooses. Big-endian byte ordering is recommended but not mandatory. 651*055d4590SKeyi Gui<p>Chunk handlers will be notified when a DDM server connects or disconnects, 652*055d4590SKeyi Guiso that they can perform setup and cleanup operations: 653*055d4590SKeyi Gui<pre class=prettyprint> 654*055d4590SKeyi Guipublic void connected() 655*055d4590SKeyi Guipublic void disconnected() 656*055d4590SKeyi Gui</pre> 657*055d4590SKeyi Gui 658*055d4590SKeyi Gui<p>The method processes the request, formulates a response, and returns it. 659*055d4590SKeyi GuiIf the method returns null, an empty JDWP success message will be returned. 660*055d4590SKeyi Gui<p>The request/response interaction is essentially asynchronous in the 661*055d4590SKeyi Guiprotocol. The packets are linked together with the JDWP message ID. 662*055d4590SKeyi Gui<p>[We could use ByteBuffer here instead of byte[], but it doesn't gain 663*055d4590SKeyi Guius much. Wrapping a ByteBuffer around an array is easy. We don't want 664*055d4590SKeyi Guito pass the full packet in because we could have multiple chunks in one 665*055d4590SKeyi Guirequest packet. The DDM code needs to collect and aggregate the responses 666*055d4590SKeyi Guito all chunks into a single JDWP response packet. Parties wanting to 667*055d4590SKeyi Guiwrite multiple chunks in response to a single chunk should send a null 668*055d4590SKeyi Guiresponse back and use "sendChunk()" to send the data independently.] 669*055d4590SKeyi Gui 670*055d4590SKeyi Gui<h3>Unsolicited event API</h3> 671*055d4590SKeyi Gui 672*055d4590SKeyi Gui<p>If a piece of code wants to send a chunk of data to the server at some 673*055d4590SKeyi Guiarbitrary time, it may do so with a method provided by 674*055d4590SKeyi Guiorg.apache.harmony.dalvik.DdmServer: 675*055d4590SKeyi Gui 676*055d4590SKeyi Gui<pre class=prettyprint> 677*055d4590SKeyi Guipublic static void sendChunk(Chunk chunk) 678*055d4590SKeyi Gui</pre> 679*055d4590SKeyi Gui 680*055d4590SKeyi Gui<p>There is no response or status code. No exceptions are thrown. 681*055d4590SKeyi Gui 682*055d4590SKeyi Gui 683*055d4590SKeyi Gui<h2>Server API</h2> 684*055d4590SKeyi Gui 685*055d4590SKeyi Gui<p>This is similar to the client side in many ways, but makes extensive 686*055d4590SKeyi Guiuse of ByteBuffer in a perhaps misguided attempt to use java.nio.channels 687*055d4590SKeyi Guiand avoid excessive thread creation and unnecessary data copying. 688*055d4590SKeyi Gui 689*055d4590SKeyi Gui<p>Upon receipt of a packet, the server will identify it as one of: 690*055d4590SKeyi Gui<ol> 691*055d4590SKeyi Gui <li>Message to be passed through to the debugger 692*055d4590SKeyi Gui <li>Response to an earlier request 693*055d4590SKeyi Gui <li>Unsolicited event packet 694*055d4590SKeyi Gui</ol> 695*055d4590SKeyi Gui<p>To handle (2), when messages are sent from the server to the client, 696*055d4590SKeyi Guithe message must be paired with a callback method. The response might be 697*055d4590SKeyi Guidelayed for a while -- or might never arrive -- so the server can't block 698*055d4590SKeyi Guiwaiting for responses from the client. 699*055d4590SKeyi Gui<p>The chunk handlers look like this: 700*055d4590SKeyi Gui<pre class=prettyprint> 701*055d4590SKeyi Guipublic void handleChunk(Client client, int type, 702*055d4590SKeyi Gui ByteBuffer data, boolean isReply, int msgId) 703*055d4590SKeyi Gui</pre> 704*055d4590SKeyi Gui<p>The arguments are: 705*055d4590SKeyi Gui<dl> 706*055d4590SKeyi Gui <dt>client 707*055d4590SKeyi Gui <dd>An object representing the client VM that send us the packet. 708*055d4590SKeyi Gui <dt>type 709*055d4590SKeyi Gui <dd>The 32-bit chunk type. 710*055d4590SKeyi Gui <dt>data 711*055d4590SKeyi Gui <dd>The data. The data's length can be determined by calling data.limit(). 712*055d4590SKeyi Gui <dt>isReply 713*055d4590SKeyi Gui <dd>Set to "true" if this was a reply to a message we sent earlier, 714*055d4590SKeyi Gui "false" if the client sent this unsolicited. 715*055d4590SKeyi Gui <dt>msgId 716*055d4590SKeyi Gui <dd>The JDWP message ID. Useful for connecting replies with requests. 717*055d4590SKeyi Gui</dl> 718*055d4590SKeyi Gui<p>If a handler doesn't like the contents of a packet, it should log an 719*055d4590SKeyi Guierror message and return. If the handler doesn't recognize the packet at 720*055d4590SKeyi Guiall, it can call the superclass' handleUnknownChunk() method. 721*055d4590SKeyi Gui 722*055d4590SKeyi Gui<p>As with the client, the server code can be notified when clients 723*055d4590SKeyi Guiconnect or disconnect. This allows the handler to send initialization 724*055d4590SKeyi Guicode immediately after a connect, or clean up after a disconnect. 725*055d4590SKeyi Gui<p>Data associated with a client can be stored in a ClientData object, 726*055d4590SKeyi Guiwhich acts as a general per-client dumping around for VM and UI state. 727*055d4590SKeyi Gui 728*055d4590SKeyi Gui 729*055d4590SKeyi Gui<P><BR> 730*055d4590SKeyi Gui 731*055d4590SKeyi Gui<HR> 732*055d4590SKeyi Gui 733*055d4590SKeyi Gui<address>Copyright © 2007 The Android Open Source Project</address> 734*055d4590SKeyi Gui 735*055d4590SKeyi Gui</body> 736*055d4590SKeyi Gui</HTML> 737