OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / frameworks / base / core / java / android / ddm / DdmHandleHeap.java
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 org.apache.harmony.dalvik.ddmc.DdmVmInternal;
23 import android.os.Debug;
24 import android.util.Config;
25 import android.util.Log;
26 import java.io.IOException;
27 import java.nio.ByteBuffer;
28
29 /**
30  * Handle native and virtual heap requests.
31  */
32 public class DdmHandleHeap extends ChunkHandler {
33
34     public static final int CHUNK_HPIF = type("HPIF");
35     public static final int CHUNK_HPSG = type("HPSG");
36     public static final int CHUNK_HPDU = type("HPDU");
37     public static final int CHUNK_HPDS = type("HPDS");
38     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);
56         DdmServer.registerHandler(CHUNK_HPDU, mInstance);
57         DdmServer.registerHandler(CHUNK_HPDS, mInstance);
58         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);
89         } else if (type == CHUNK_HPDU) {
90             return handleHPDU(request);
91         } else if (type == CHUNK_HPDS) {
92             return handleHPDS(request);
93         } 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     /*
110      * Handle a "HeaP InFo" request.
111      */
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     /*
150      * 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;
174         } catch (RuntimeException re) {
175             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     /*
184      * 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     /*
216      * 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