blob: fa0fbbfe1658c3ee04edf47969d07e6cd7bd99c5 [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.Config;
25import android.util.Log;
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070026import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import java.nio.ByteBuffer;
28
29/**
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070030 * Handle native and virtual heap requests.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031 */
32public class DdmHandleHeap extends ChunkHandler {
33
34 public static final int CHUNK_HPIF = type("HPIF");
35 public static final int CHUNK_HPSG = type("HPSG");
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070036 public static final int CHUNK_HPDU = type("HPDU");
Andy McFadden07a96612010-01-28 16:54:37 -080037 public static final int CHUNK_HPDS = type("HPDS");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 public static final int CHUNK_NHSG = type("NHSG");
39 public static final int CHUNK_HPGC = type("HPGC");
40 public static final int CHUNK_REAE = type("REAE");
41 public static final int CHUNK_REAQ = type("REAQ");
42 public static final int CHUNK_REAL = type("REAL");
43
44 private static DdmHandleHeap mInstance = new DdmHandleHeap();
45
46
47 /* singleton, do not instantiate */
48 private DdmHandleHeap() {}
49
50 /**
51 * Register for the messages we're interested in.
52 */
53 public static void register() {
54 DdmServer.registerHandler(CHUNK_HPIF, mInstance);
55 DdmServer.registerHandler(CHUNK_HPSG, mInstance);
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070056 DdmServer.registerHandler(CHUNK_HPDU, mInstance);
Andy McFadden07a96612010-01-28 16:54:37 -080057 DdmServer.registerHandler(CHUNK_HPDS, mInstance);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080058 DdmServer.registerHandler(CHUNK_NHSG, mInstance);
59 DdmServer.registerHandler(CHUNK_HPGC, mInstance);
60 DdmServer.registerHandler(CHUNK_REAE, mInstance);
61 DdmServer.registerHandler(CHUNK_REAQ, mInstance);
62 DdmServer.registerHandler(CHUNK_REAL, mInstance);
63 }
64
65 /**
66 * Called when the DDM server connects. The handler is allowed to
67 * send messages to the server.
68 */
69 public void connected() {}
70
71 /**
72 * Called when the DDM server disconnects. Can be used to disable
73 * periodic transmissions or clean up saved state.
74 */
75 public void disconnected() {}
76
77 /**
78 * Handle a chunk of data.
79 */
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_HPIF) {
86 return handleHPIF(request);
87 } else if (type == CHUNK_HPSG) {
88 return handleHPSGNHSG(request, false);
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -070089 } else if (type == CHUNK_HPDU) {
90 return handleHPDU(request);
Andy McFadden07a96612010-01-28 16:54:37 -080091 } else if (type == CHUNK_HPDS) {
92 return handleHPDS(request);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080093 } else if (type == CHUNK_NHSG) {
94 return handleHPSGNHSG(request, true);
95 } else if (type == CHUNK_HPGC) {
96 return handleHPGC(request);
97 } else if (type == CHUNK_REAE) {
98 return handleREAE(request);
99 } else if (type == CHUNK_REAQ) {
100 return handleREAQ(request);
101 } else if (type == CHUNK_REAL) {
102 return handleREAL(request);
103 } else {
104 throw new RuntimeException("Unknown packet "
105 + ChunkHandler.name(type));
106 }
107 }
108
109 /*
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700110 * Handle a "HeaP InFo" request.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 */
112 private Chunk handleHPIF(Chunk request) {
113 ByteBuffer in = wrapChunk(request);
114
115 int when = in.get();
116 if (Config.LOGV)
117 Log.v("ddm-heap", "Heap segment enable: when=" + when);
118
119 boolean ok = DdmVmInternal.heapInfoNotify(when);
120 if (!ok) {
121 return createFailChunk(1, "Unsupported HPIF what");
122 } else {
123 return null; // empty response
124 }
125 }
126
127 /*
128 * Handle a "HeaP SeGment" or "Native Heap SeGment" request.
129 */
130 private Chunk handleHPSGNHSG(Chunk request, boolean isNative) {
131 ByteBuffer in = wrapChunk(request);
132
133 int when = in.get();
134 int what = in.get();
135 if (Config.LOGV)
136 Log.v("ddm-heap", "Heap segment enable: when=" + when
137 + ", what=" + what + ", isNative=" + isNative);
138
139 boolean ok = DdmVmInternal.heapSegmentNotify(when, what, isNative);
140 if (!ok) {
141 return createFailChunk(1, "Unsupported HPSG what/when");
142 } else {
143 // TODO: if "when" is non-zero and we want to see a dump
144 // right away, initiate a GC.
145 return null; // empty response
146 }
147 }
148
149 /*
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700150 * Handle a "HeaP DUmp" request.
151 *
152 * This currently just returns a result code. We could pull up
153 * the entire contents of the file and return them, but hprof dump
154 * files can be a few megabytes.
155 */
156 private Chunk handleHPDU(Chunk request) {
157 ByteBuffer in = wrapChunk(request);
158 byte result;
159
160 /* get the filename for the output file */
161 int len = in.getInt();
162 String fileName = getString(in, len);
163 if (Config.LOGD)
164 Log.d("ddm-heap", "Heap dump: file='" + fileName + "'");
165
166 try {
167 Debug.dumpHprofData(fileName);
168 result = 0;
169 } catch (UnsupportedOperationException uoe) {
170 Log.w("ddm-heap", "hprof dumps not supported in this VM");
171 result = -1;
172 } catch (IOException ioe) {
173 result = -1;
Andy McFadden07a96612010-01-28 16:54:37 -0800174 } catch (RuntimeException re) {
The Android Open Source Project7b0b1ed2009-03-18 22:20:26 -0700175 result = -1;
176 }
177
178 /* create a non-empty reply so the handler fires on completion */
179 byte[] reply = { result };
180 return new Chunk(CHUNK_HPDU, reply, 0, reply.length);
181 }
182
183 /*
Andy McFadden07a96612010-01-28 16:54:37 -0800184 * Handle a "HeaP Dump Streaming" request.
185 *
186 * This tells the VM to create a heap dump and send it directly to
187 * DDMS. The dumps are large enough that we don't want to copy the
188 * data into a byte[] and send it from here.
189 */
190 private Chunk handleHPDS(Chunk request) {
191 ByteBuffer in = wrapChunk(request);
192 byte result;
193
194 /* get the filename for the output file */
195 if (Config.LOGD)
196 Log.d("ddm-heap", "Heap dump: [DDMS]");
197
198 String failMsg = null;
199 try {
200 Debug.dumpHprofDataDdms();
201 } catch (UnsupportedOperationException uoe) {
202 failMsg = "hprof dumps not supported in this VM";
203 } catch (RuntimeException re) {
204 failMsg = "Exception: " + re.getMessage();
205 }
206
207 if (failMsg != null) {
208 Log.w("ddm-heap", failMsg);
209 return createFailChunk(1, failMsg);
210 } else {
211 return null;
212 }
213 }
214
215 /*
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 * Handle a "HeaP Garbage Collection" request.
217 */
218 private Chunk handleHPGC(Chunk request) {
219 //ByteBuffer in = wrapChunk(request);
220
221 if (Config.LOGD)
222 Log.d("ddm-heap", "Heap GC request");
223 System.gc();
224
225 return null; // empty response
226 }
227
228 /*
229 * Handle a "REcent Allocation Enable" request.
230 */
231 private Chunk handleREAE(Chunk request) {
232 ByteBuffer in = wrapChunk(request);
233 boolean enable;
234
235 enable = (in.get() != 0);
236
237 if (Config.LOGD)
238 Log.d("ddm-heap", "Recent allocation enable request: " + enable);
239
240 DdmVmInternal.enableRecentAllocations(enable);
241
242 return null; // empty response
243 }
244
245 /*
246 * Handle a "REcent Allocation Query" request.
247 */
248 private Chunk handleREAQ(Chunk request) {
249 //ByteBuffer in = wrapChunk(request);
250
251 byte[] reply = new byte[1];
252 reply[0] = DdmVmInternal.getRecentAllocationStatus() ? (byte)1 :(byte)0;
253 return new Chunk(CHUNK_REAQ, reply, 0, reply.length);
254 }
255
256 /*
257 * Handle a "REcent ALlocations" request.
258 */
259 private Chunk handleREAL(Chunk request) {
260 //ByteBuffer in = wrapChunk(request);
261
262 if (Config.LOGD)
263 Log.d("ddm-heap", "Recent allocations request");
264
265 /* generate the reply in a ready-to-go format */
266 byte[] reply = DdmVmInternal.getRecentAllocations();
267 return new Chunk(CHUNK_REAL, reply, 0, reply.length);
268 }
269}
270