blob: cece556d6107d62783d37d4930321f70d1d725a0 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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
17package android.ddm;
18
19import org.apache.harmony.dalvik.ddmc.Chunk;
20import org.apache.harmony.dalvik.ddmc.ChunkHandler;
21import org.apache.harmony.dalvik.ddmc.DdmServer;
22import org.apache.harmony.dalvik.ddmc.DdmVmInternal;
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070023import android.os.Debug;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.util.Log;
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070025import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import java.nio.ByteBuffer;
27
28/**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070029 * Handle native and virtual heap requests.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030 */
31public class DdmHandleHeap extends ChunkHandler {
32
33 public static final int CHUNK_HPIF = type("HPIF");
34 public static final int CHUNK_HPSG = type("HPSG");
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070035 public static final int CHUNK_HPDU = type("HPDU");
Andy McFadden07a96612010-01-28 16:54:37 -080036 public static final int CHUNK_HPDS = type("HPDS");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 public static final int CHUNK_NHSG = type("NHSG");
38 public static final int CHUNK_HPGC = type("HPGC");
39 public static final int CHUNK_REAE = type("REAE");
40 public static final int CHUNK_REAQ = type("REAQ");
41 public static final int CHUNK_REAL = type("REAL");
42
43 private static DdmHandleHeap mInstance = new DdmHandleHeap();
44
45
46 /* singleton, do not instantiate */
47 private DdmHandleHeap() {}
48
49 /**
50 * Register for the messages we're interested in.
51 */
52 public static void register() {
53 DdmServer.registerHandler(CHUNK_HPIF, mInstance);
54 DdmServer.registerHandler(CHUNK_HPSG, mInstance);
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070055 DdmServer.registerHandler(CHUNK_HPDU, mInstance);
Andy McFadden07a96612010-01-28 16:54:37 -080056 DdmServer.registerHandler(CHUNK_HPDS, mInstance);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080057 DdmServer.registerHandler(CHUNK_NHSG, mInstance);
58 DdmServer.registerHandler(CHUNK_HPGC, mInstance);
59 DdmServer.registerHandler(CHUNK_REAE, mInstance);
60 DdmServer.registerHandler(CHUNK_REAQ, mInstance);
61 DdmServer.registerHandler(CHUNK_REAL, mInstance);
62 }
63
64 /**
65 * Called when the DDM server connects. The handler is allowed to
66 * send messages to the server.
67 */
68 public void connected() {}
69
70 /**
71 * Called when the DDM server disconnects. Can be used to disable
72 * periodic transmissions or clean up saved state.
73 */
74 public void disconnected() {}
75
76 /**
77 * Handle a chunk of data.
78 */
79 public Chunk handleChunk(Chunk request) {
Joe Onorato43a17652011-04-06 19:22:23 -070080 if (false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
82 int type = request.type;
83
84 if (type == CHUNK_HPIF) {
85 return handleHPIF(request);
86 } else if (type == CHUNK_HPSG) {
87 return handleHPSGNHSG(request, false);
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070088 } else if (type == CHUNK_HPDU) {
89 return handleHPDU(request);
Andy McFadden07a96612010-01-28 16:54:37 -080090 } else if (type == CHUNK_HPDS) {
91 return handleHPDS(request);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080092 } else if (type == CHUNK_NHSG) {
93 return handleHPSGNHSG(request, true);
94 } else if (type == CHUNK_HPGC) {
95 return handleHPGC(request);
96 } else if (type == CHUNK_REAE) {
97 return handleREAE(request);
98 } else if (type == CHUNK_REAQ) {
99 return handleREAQ(request);
100 } else if (type == CHUNK_REAL) {
101 return handleREAL(request);
102 } else {
103 throw new RuntimeException("Unknown packet "
104 + ChunkHandler.name(type));
105 }
106 }
107
108 /*
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700109 * Handle a "HeaP InFo" request.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800110 */
111 private Chunk handleHPIF(Chunk request) {
112 ByteBuffer in = wrapChunk(request);
113
114 int when = in.get();
Joe Onorato43a17652011-04-06 19:22:23 -0700115 if (false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800116 Log.v("ddm-heap", "Heap segment enable: when=" + when);
117
118 boolean ok = DdmVmInternal.heapInfoNotify(when);
119 if (!ok) {
120 return createFailChunk(1, "Unsupported HPIF what");
121 } else {
122 return null; // empty response
123 }
124 }
125
126 /*
127 * Handle a "HeaP SeGment" or "Native Heap SeGment" request.
128 */
129 private Chunk handleHPSGNHSG(Chunk request, boolean isNative) {
130 ByteBuffer in = wrapChunk(request);
131
132 int when = in.get();
133 int what = in.get();
Joe Onorato43a17652011-04-06 19:22:23 -0700134 if (false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 Log.v("ddm-heap", "Heap segment enable: when=" + when
136 + ", what=" + what + ", isNative=" + isNative);
137
138 boolean ok = DdmVmInternal.heapSegmentNotify(when, what, isNative);
139 if (!ok) {
140 return createFailChunk(1, "Unsupported HPSG what/when");
141 } else {
142 // TODO: if "when" is non-zero and we want to see a dump
143 // right away, initiate a GC.
144 return null; // empty response
145 }
146 }
147
148 /*
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700149 * Handle a "HeaP DUmp" request.
150 *
151 * This currently just returns a result code. We could pull up
152 * the entire contents of the file and return them, but hprof dump
153 * files can be a few megabytes.
154 */
155 private Chunk handleHPDU(Chunk request) {
156 ByteBuffer in = wrapChunk(request);
157 byte result;
158
159 /* get the filename for the output file */
160 int len = in.getInt();
161 String fileName = getString(in, len);
Joe Onorato43a17652011-04-06 19:22:23 -0700162 if (false)
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700163 Log.d("ddm-heap", "Heap dump: file='" + fileName + "'");
164
165 try {
166 Debug.dumpHprofData(fileName);
167 result = 0;
168 } catch (UnsupportedOperationException uoe) {
169 Log.w("ddm-heap", "hprof dumps not supported in this VM");
170 result = -1;
171 } catch (IOException ioe) {
172 result = -1;
Andy McFadden07a96612010-01-28 16:54:37 -0800173 } catch (RuntimeException re) {
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700174 result = -1;
175 }
176
177 /* create a non-empty reply so the handler fires on completion */
178 byte[] reply = { result };
179 return new Chunk(CHUNK_HPDU, reply, 0, reply.length);
180 }
181
182 /*
Andy McFadden07a96612010-01-28 16:54:37 -0800183 * Handle a "HeaP Dump Streaming" request.
184 *
185 * This tells the VM to create a heap dump and send it directly to
186 * DDMS. The dumps are large enough that we don't want to copy the
187 * data into a byte[] and send it from here.
188 */
189 private Chunk handleHPDS(Chunk request) {
190 ByteBuffer in = wrapChunk(request);
191 byte result;
192
193 /* get the filename for the output file */
Joe Onorato43a17652011-04-06 19:22:23 -0700194 if (false)
Andy McFadden07a96612010-01-28 16:54:37 -0800195 Log.d("ddm-heap", "Heap dump: [DDMS]");
196
197 String failMsg = null;
198 try {
199 Debug.dumpHprofDataDdms();
200 } catch (UnsupportedOperationException uoe) {
201 failMsg = "hprof dumps not supported in this VM";
202 } catch (RuntimeException re) {
203 failMsg = "Exception: " + re.getMessage();
204 }
205
206 if (failMsg != null) {
207 Log.w("ddm-heap", failMsg);
208 return createFailChunk(1, failMsg);
209 } else {
210 return null;
211 }
212 }
213
214 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 * Handle a "HeaP Garbage Collection" request.
216 */
217 private Chunk handleHPGC(Chunk request) {
218 //ByteBuffer in = wrapChunk(request);
219
Joe Onorato43a17652011-04-06 19:22:23 -0700220 if (false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800221 Log.d("ddm-heap", "Heap GC request");
222 System.gc();
223
224 return null; // empty response
225 }
226
227 /*
228 * Handle a "REcent Allocation Enable" request.
229 */
230 private Chunk handleREAE(Chunk request) {
231 ByteBuffer in = wrapChunk(request);
232 boolean enable;
233
234 enable = (in.get() != 0);
235
Joe Onorato43a17652011-04-06 19:22:23 -0700236 if (false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 Log.d("ddm-heap", "Recent allocation enable request: " + enable);
238
239 DdmVmInternal.enableRecentAllocations(enable);
240
241 return null; // empty response
242 }
243
244 /*
245 * Handle a "REcent Allocation Query" request.
246 */
247 private Chunk handleREAQ(Chunk request) {
248 //ByteBuffer in = wrapChunk(request);
249
250 byte[] reply = new byte[1];
251 reply[0] = DdmVmInternal.getRecentAllocationStatus() ? (byte)1 :(byte)0;
252 return new Chunk(CHUNK_REAQ, reply, 0, reply.length);
253 }
254
255 /*
256 * Handle a "REcent ALlocations" request.
257 */
258 private Chunk handleREAL(Chunk request) {
259 //ByteBuffer in = wrapChunk(request);
260
Joe Onorato43a17652011-04-06 19:22:23 -0700261 if (false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800262 Log.d("ddm-heap", "Recent allocations request");
263
264 /* generate the reply in a ready-to-go format */
265 byte[] reply = DdmVmInternal.getRecentAllocations();
266 return new Chunk(CHUNK_REAL, reply, 0, reply.length);
267 }
268}
269