1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.ddmlib; 18 19 import java.io.IOException; 20 import java.nio.ByteBuffer; 21 22 /** 23 * Handle the "hello" chunk (HELO) and feature discovery. 24 */ 25 final class HandleHello extends ChunkHandler { 26 27 public static final int CHUNK_HELO = ChunkHandler.type("HELO"); 28 public static final int CHUNK_FEAT = ChunkHandler.type("FEAT"); 29 30 private static final HandleHello mInst = new HandleHello(); 31 32 private HandleHello() {} 33 34 /** 35 * Register for the packets we expect to get from the client. 36 */ 37 public static void register(MonitorThread mt) { 38 mt.registerChunkHandler(CHUNK_HELO, mInst); 39 } 40 41 /** 42 * Client is ready. 43 */ 44 @Override 45 public void clientReady(Client client) throws IOException { 46 Log.d("ddm-hello", "Now ready: " + client); 47 } 48 49 /** 50 * Client went away. 51 */ 52 @Override 53 public void clientDisconnected(Client client) { 54 Log.d("ddm-hello", "Now disconnected: " + client); 55 } 56 57 /** 58 * Sends HELLO-type commands to the VM after a good handshake. 59 * @param client 60 * @param serverProtocolVersion 61 * @throws IOException 62 */ 63 public static void sendHelloCommands(Client client, int serverProtocolVersion) 64 throws IOException { 65 sendHELO(client, serverProtocolVersion); 66 sendFEAT(client); 67 HandleProfiling.sendMPRQ(client); 68 } 69 70 /** 71 * Chunk handler entry point. 72 */ 73 @Override 74 public void handleChunk(Client client, int type, ByteBuffer data, boolean isReply, int msgId) { 75 76 Log.d("ddm-hello", "handling " + ChunkHandler.name(type)); 77 78 if (type == CHUNK_HELO) { 79 assert isReply; 80 handleHELO(client, data); 81 } else if (type == CHUNK_FEAT) { 82 handleFEAT(client, data); 83 } else { 84 handleUnknownChunk(client, type, data, isReply, msgId); 85 } 86 } 87 88 /* 89 * Handle a reply to our HELO message. 90 */ 91 private static void handleHELO(Client client, ByteBuffer data) { 92 int version, pid, vmIdentLen, appNameLen; 93 String vmIdent, appName; 94 95 version = data.getInt(); 96 pid = data.getInt(); 97 vmIdentLen = data.getInt(); 98 appNameLen = data.getInt(); 99 100 vmIdent = getString(data, vmIdentLen); 101 appName = getString(data, appNameLen); 102 103 Log.d("ddm-hello", "HELO: v=" + version + ", pid=" + pid 104 + ", vm='" + vmIdent + "', app='" + appName + "'"); 105 106 ClientData cd = client.getClientData(); 107 108 synchronized (cd) { 109 if (cd.getPid() == pid) { 110 cd.setVmIdentifier(vmIdent); 111 cd.setClientDescription(appName); 112 cd.isDdmAware(true); 113 } else { 114 Log.e("ddm-hello", "Received pid (" + pid + ") does not match client pid (" 115 + cd.getPid() + ")"); 116 } 117 } 118 119 client = checkDebuggerPortForAppName(client, appName); 120 121 if (client != null) { 122 client.update(Client.CHANGE_NAME); 123 } 124 } 125 126 127 /** 128 * Send a HELO request to the client. 129 */ 130 public static void sendHELO(Client client, int serverProtocolVersion) 131 throws IOException 132 { 133 ByteBuffer rawBuf = allocBuffer(4); 134 JdwpPacket packet = new JdwpPacket(rawBuf); 135 ByteBuffer buf = getChunkDataBuf(rawBuf); 136 137 buf.putInt(serverProtocolVersion); 138 139 finishChunkPacket(packet, CHUNK_HELO, buf.position()); 140 Log.d("ddm-hello", "Sending " + name(CHUNK_HELO) 141 + " ID=0x" + Integer.toHexString(packet.getId())); 142 client.sendAndConsume(packet, mInst); 143 } 144 145 /** 146 * Handle a reply to our FEAT request. 147 */ 148 private static void handleFEAT(Client client, ByteBuffer data) { 149 int featureCount; 150 int i; 151 152 featureCount = data.getInt(); 153 for (i = 0; i < featureCount; i++) { 154 int len = data.getInt(); 155 String feature = getString(data, len); 156 client.getClientData().addFeature(feature); 157 158 Log.d("ddm-hello", "Feature: " + feature); 159 } 160 } 161 162 /** 163 * Send a FEAT request to the client. 164 */ 165 public static void sendFEAT(Client client) throws IOException { 166 ByteBuffer rawBuf = allocBuffer(0); 167 JdwpPacket packet = new JdwpPacket(rawBuf); 168 ByteBuffer buf = getChunkDataBuf(rawBuf); 169 170 // no data 171 172 finishChunkPacket(packet, CHUNK_FEAT, buf.position()); 173 Log.d("ddm-heap", "Sending " + name(CHUNK_FEAT)); 174 client.sendAndConsume(packet, mInst); 175 } 176 } 177 178