DdmHandleProfiling.java revision 6c7bac69f5e1096a93983817d6e093dd81fc7220
1/*
2 * Copyright (C) 2009 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 android.os.Debug;
23import android.util.Log;
24import java.io.IOException;
25import java.nio.ByteBuffer;
26
27/**
28 * Handle profiling requests.
29 */
30public class DdmHandleProfiling extends ChunkHandler {
31
32    public static final int CHUNK_MPRS = type("MPRS");
33    public static final int CHUNK_MPRE = type("MPRE");
34    public static final int CHUNK_MPSS = type("MPSS");
35    public static final int CHUNK_MPSE = type("MPSE");
36    public static final int CHUNK_MPRQ = type("MPRQ");
37    public static final int CHUNK_SPSS = type("SPSS");
38    public static final int CHUNK_SPSE = type("SPSE");
39
40    private static final boolean DEBUG = false;
41    private static DdmHandleProfiling mInstance = new DdmHandleProfiling();
42
43
44    /* singleton, do not instantiate */
45    private DdmHandleProfiling() {}
46
47    /**
48     * Register for the messages we're interested in.
49     */
50    public static void register() {
51        DdmServer.registerHandler(CHUNK_MPRS, mInstance);
52        DdmServer.registerHandler(CHUNK_MPRE, mInstance);
53        DdmServer.registerHandler(CHUNK_MPSS, mInstance);
54        DdmServer.registerHandler(CHUNK_MPSE, mInstance);
55        DdmServer.registerHandler(CHUNK_MPRQ, mInstance);
56        DdmServer.registerHandler(CHUNK_SPSS, mInstance);
57        DdmServer.registerHandler(CHUNK_SPSE, mInstance);
58    }
59
60    /**
61     * Called when the DDM server connects.  The handler is allowed to
62     * send messages to the server.
63     */
64    public void connected() {}
65
66    /**
67     * Called when the DDM server disconnects.  Can be used to disable
68     * periodic transmissions or clean up saved state.
69     */
70    public void disconnected() {}
71
72    /**
73     * Handle a chunk of data.
74     */
75    public Chunk handleChunk(Chunk request) {
76        if (DEBUG)
77            Log.v("ddm-heap", "Handling " + name(request.type) + " chunk");
78        int type = request.type;
79
80        if (type == CHUNK_MPRS) {
81            return handleMPRS(request);
82        } else if (type == CHUNK_MPRE) {
83            return handleMPRE(request);
84        } else if (type == CHUNK_MPSS) {
85            return handleMPSS(request);
86        } else if (type == CHUNK_MPSE) {
87            return handleMPSEOrSPSE(request, "Method");
88        } else if (type == CHUNK_MPRQ) {
89            return handleMPRQ(request);
90        } else if (type == CHUNK_SPSS) {
91            return handleSPSS(request);
92        } else if (type == CHUNK_SPSE) {
93            return handleMPSEOrSPSE(request, "Sample");
94        } else {
95            throw new RuntimeException("Unknown packet "
96                + ChunkHandler.name(type));
97        }
98    }
99
100    /*
101     * Handle a "Method PRofiling Start" request.
102     */
103    private Chunk handleMPRS(Chunk request) {
104        ByteBuffer in = wrapChunk(request);
105
106        int bufferSize = in.getInt();
107        int flags = in.getInt();
108        int len = in.getInt();
109        String fileName = getString(in, len);
110        if (DEBUG)
111            Log.v("ddm-heap", "Method profiling start: filename='" + fileName
112                + "', size=" + bufferSize + ", flags=" + flags);
113
114        try {
115            Debug.startMethodTracing(fileName, bufferSize, flags);
116            return null;        // empty response
117        } catch (RuntimeException re) {
118            return createFailChunk(1, re.getMessage());
119        }
120    }
121
122    /*
123     * Handle a "Method PRofiling End" request.
124     */
125    private Chunk handleMPRE(Chunk request) {
126        byte result;
127
128        try {
129            Debug.stopMethodTracing();
130            result = 0;
131        } catch (RuntimeException re) {
132            Log.w("ddm-heap", "Method profiling end failed: "
133                + re.getMessage());
134            result = 1;
135        }
136
137        /* create a non-empty reply so the handler fires on completion */
138        byte[] reply = { result };
139        return new Chunk(CHUNK_MPRE, reply, 0, reply.length);
140    }
141
142    /*
143     * Handle a "Method Profiling w/Streaming Start" request.
144     */
145    private Chunk handleMPSS(Chunk request) {
146        ByteBuffer in = wrapChunk(request);
147
148        int bufferSize = in.getInt();
149        int flags = in.getInt();
150        if (DEBUG) {
151            Log.v("ddm-heap", "Method prof stream start: size=" + bufferSize
152                + ", flags=" + flags);
153        }
154
155        try {
156            Debug.startMethodTracingDdms(bufferSize, flags, false, 0);
157            return null;        // empty response
158        } catch (RuntimeException re) {
159            return createFailChunk(1, re.getMessage());
160        }
161    }
162
163    /*
164     * Handle a "Method Profiling w/Streaming End" request or a
165     * "Sample Profiling w/Streaming End" request.
166     */
167    private Chunk handleMPSEOrSPSE(Chunk request, String type) {
168        if (DEBUG) {
169            Log.v("ddm-heap", type + " prof stream end");
170        }
171
172        try {
173            Debug.stopMethodTracing();
174        } catch (RuntimeException re) {
175            Log.w("ddm-heap", type + " prof stream end failed: "
176                + re.getMessage());
177            return createFailChunk(1, re.getMessage());
178        }
179
180        /* VM sent the (perhaps very large) response directly */
181        return null;
182    }
183
184    /*
185     * Handle a "Method PRofiling Query" request.
186     */
187    private Chunk handleMPRQ(Chunk request) {
188        int result = Debug.isMethodTracingActive() ? 1 : 0;
189
190        /* create a non-empty reply so the handler fires on completion */
191        byte[] reply = { (byte) result };
192        return new Chunk(CHUNK_MPRQ, reply, 0, reply.length);
193    }
194
195    /*
196     * Handle a "Sample Profiling w/Streaming Start" request.
197     */
198    private Chunk handleSPSS(Chunk request) {
199        ByteBuffer in = wrapChunk(request);
200
201        int bufferSize = in.getInt();
202        int flags = in.getInt();
203        int interval = in.getInt();
204        if (DEBUG) {
205            Log.v("ddm-heap", "Sample prof stream start: size=" + bufferSize
206                + ", flags=" + flags + ", interval=" + interval);
207        }
208
209        try {
210            Debug.startMethodTracingDdms(bufferSize, flags, true, interval);
211            return null;        // empty response
212        } catch (RuntimeException re) {
213            return createFailChunk(1, re.getMessage());
214        }
215    }
216}
217
218