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 android.ddm; 18 19 import org.apache.harmony.dalvik.ddmc.Chunk; 20 import org.apache.harmony.dalvik.ddmc.ChunkHandler; 21 import org.apache.harmony.dalvik.ddmc.DdmServer; 22 import android.util.Config; 23 import android.util.Log; 24 import android.os.Debug; 25 26 import java.nio.ByteBuffer; 27 28 /** 29 * Handle "hello" messages and feature discovery. 30 */ 31 public class DdmHandleHello extends ChunkHandler { 32 33 public static final int CHUNK_HELO = type("HELO"); 34 public static final int CHUNK_WAIT = type("WAIT"); 35 public static final int CHUNK_FEAT = type("FEAT"); 36 37 private static DdmHandleHello mInstance = new DdmHandleHello(); 38 39 40 /* singleton, do not instantiate */ DdmHandleHello()41 private DdmHandleHello() {} 42 43 /** 44 * Register for the messages we're interested in. 45 */ register()46 public static void register() { 47 DdmServer.registerHandler(CHUNK_HELO, mInstance); 48 DdmServer.registerHandler(CHUNK_FEAT, mInstance); 49 } 50 51 /** 52 * Called when the DDM server connects. The handler is allowed to 53 * send messages to the server. 54 */ connected()55 public void connected() { 56 if (Config.LOGV) 57 Log.v("ddm-hello", "Connected!"); 58 59 if (false) { 60 /* test spontaneous transmission */ 61 byte[] data = new byte[] { 0, 1, 2, 3, 4, -4, -3, -2, -1, 127 }; 62 Chunk testChunk = 63 new Chunk(ChunkHandler.type("TEST"), data, 1, data.length-2); 64 DdmServer.sendChunk(testChunk); 65 } 66 } 67 68 /** 69 * Called when the DDM server disconnects. Can be used to disable 70 * periodic transmissions or clean up saved state. 71 */ disconnected()72 public void disconnected() { 73 if (Config.LOGV) 74 Log.v("ddm-hello", "Disconnected!"); 75 } 76 77 /** 78 * Handle a chunk of data. 79 */ handleChunk(Chunk request)80 public Chunk handleChunk(Chunk request) { 81 if (Config.LOGV) 82 Log.v("ddm-heap", "Handling " + name(request.type) + " chunk"); 83 int type = request.type; 84 85 if (type == CHUNK_HELO) { 86 return handleHELO(request); 87 } else if (type == CHUNK_FEAT) { 88 return handleFEAT(request); 89 } else { 90 throw new RuntimeException("Unknown packet " 91 + ChunkHandler.name(type)); 92 } 93 } 94 95 /* 96 * Handle introductory packet. 97 */ handleHELO(Chunk request)98 private Chunk handleHELO(Chunk request) { 99 if (false) 100 return createFailChunk(123, "This is a test"); 101 102 /* 103 * Process the request. 104 */ 105 ByteBuffer in = wrapChunk(request); 106 107 int serverProtoVers = in.getInt(); 108 if (Config.LOGV) 109 Log.v("ddm-hello", "Server version is " + serverProtoVers); 110 111 /* 112 * Create a response. 113 */ 114 String vmName = System.getProperty("java.vm.name", "?"); 115 String vmVersion = System.getProperty("java.vm.version", "?"); 116 String vmIdent = vmName + " v" + vmVersion; 117 118 //String appName = android.app.ActivityThread.currentPackageName(); 119 //if (appName == null) 120 // appName = "unknown"; 121 String appName = DdmHandleAppName.getAppName(); 122 123 ByteBuffer out = ByteBuffer.allocate(16 124 + vmIdent.length()*2 + appName.length()*2); 125 out.order(ChunkHandler.CHUNK_ORDER); 126 out.putInt(DdmServer.CLIENT_PROTOCOL_VERSION); 127 out.putInt(android.os.Process.myPid()); 128 out.putInt(vmIdent.length()); 129 out.putInt(appName.length()); 130 putString(out, vmIdent); 131 putString(out, appName); 132 133 Chunk reply = new Chunk(CHUNK_HELO, out); 134 135 /* 136 * Take the opportunity to inform DDMS if we are waiting for a 137 * debugger to attach. 138 */ 139 if (Debug.waitingForDebugger()) 140 sendWAIT(0); 141 142 return reply; 143 } 144 145 /* 146 * Handle request for list of supported features. 147 */ handleFEAT(Chunk request)148 private Chunk handleFEAT(Chunk request) { 149 // TODO: query the VM to ensure that support for these features 150 // is actually compiled in 151 final String[] features = Debug.getVmFeatureList(); 152 153 if (Config.LOGV) 154 Log.v("ddm-heap", "Got feature list request"); 155 156 int size = 4 + 4 * features.length; 157 for (int i = features.length-1; i >= 0; i--) 158 size += features[i].length() * 2; 159 160 ByteBuffer out = ByteBuffer.allocate(size); 161 out.order(ChunkHandler.CHUNK_ORDER); 162 out.putInt(features.length); 163 for (int i = features.length-1; i >= 0; i--) { 164 out.putInt(features[i].length()); 165 putString(out, features[i]); 166 } 167 168 return new Chunk(CHUNK_FEAT, out); 169 } 170 171 /** 172 * Send up a WAIT chunk. The only currently defined value for "reason" 173 * is zero, which means "waiting for a debugger". 174 */ sendWAIT(int reason)175 public static void sendWAIT(int reason) { 176 byte[] data = new byte[] { (byte) reason }; 177 Chunk waitChunk = new Chunk(CHUNK_WAIT, data, 0, 1); 178 DdmServer.sendChunk(waitChunk); 179 } 180 } 181 182