• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.ddmlib;
18 
19 import com.android.ddmlib.ClientData.IMethodProfilingHandler;
20 import com.android.ddmlib.ClientData.MethodProfilingStatus;
21 
22 import java.io.IOException;
23 import java.nio.ByteBuffer;
24 
25 /**
26  * Handle heap status updates.
27  */
28 final class HandleProfiling extends ChunkHandler {
29 
30     public static final int CHUNK_MPRS = type("MPRS");
31     public static final int CHUNK_MPRE = type("MPRE");
32     public static final int CHUNK_MPRQ = type("MPRQ");
33     public static final int CHUNK_FAIL = type("FAIL");
34 
35     private static final HandleProfiling mInst = new HandleProfiling();
36 
HandleProfiling()37     private HandleProfiling() {}
38 
39     /**
40      * Register for the packets we expect to get from the client.
41      */
register(MonitorThread mt)42     public static void register(MonitorThread mt) {
43         mt.registerChunkHandler(CHUNK_MPRE, mInst);
44         mt.registerChunkHandler(CHUNK_MPRQ, mInst);
45     }
46 
47     /**
48      * Client is ready.
49      */
50     @Override
clientReady(Client client)51     public void clientReady(Client client) throws IOException {}
52 
53     /**
54      * Client went away.
55      */
56     @Override
clientDisconnected(Client client)57     public void clientDisconnected(Client client) {}
58 
59     /**
60      * Chunk handler entry point.
61      */
62     @Override
handleChunk(Client client, int type, ByteBuffer data, boolean isReply, int msgId)63     public void handleChunk(Client client, int type, ByteBuffer data,
64         boolean isReply, int msgId) {
65 
66         Log.d("ddm-prof", "handling " + ChunkHandler.name(type));
67 
68         if (type == CHUNK_MPRE) {
69             handleMPRE(client, data);
70         } else if (type == CHUNK_MPRQ) {
71             handleMPRQ(client, data);
72         } else if (type == CHUNK_FAIL) {
73             handleFAIL(client, data);
74         } else {
75             handleUnknownChunk(client, type, data, isReply, msgId);
76         }
77     }
78 
79     /**
80      * Send a MPRS (Method PRofiling Start) request to the client.
81      *
82      * The arguments to this method will eventually be passed to
83      * android.os.Debug.startMethodTracing() on the device.
84      *
85      * @param fileName is the name of the file to which profiling data
86      *          will be written (on the device); it will have ".trace"
87      *          appended if necessary
88      * @param bufferSize is the desired buffer size in bytes (8MB is good)
89      * @param flags see startMethodTracing() docs; use 0 for default behavior
90      */
sendMPRS(Client client, String fileName, int bufferSize, int flags)91     public static void sendMPRS(Client client, String fileName, int bufferSize,
92         int flags) throws IOException {
93 
94         ByteBuffer rawBuf = allocBuffer(3*4 + fileName.length() * 2);
95         JdwpPacket packet = new JdwpPacket(rawBuf);
96         ByteBuffer buf = getChunkDataBuf(rawBuf);
97 
98         buf.putInt(bufferSize);
99         buf.putInt(flags);
100         buf.putInt(fileName.length());
101         putString(buf, fileName);
102 
103         finishChunkPacket(packet, CHUNK_MPRS, buf.position());
104         Log.d("ddm-prof", "Sending " + name(CHUNK_MPRS) + " '" + fileName
105             + "', size=" + bufferSize + ", flags=" + flags);
106         client.sendAndConsume(packet, mInst);
107 
108         // record the filename we asked for.
109         client.getClientData().setPendingMethodProfiling(fileName);
110 
111         // send a status query. this ensure that the status is properly updated if for some
112         // reason starting the tracing failed.
113         sendMPRQ(client);
114     }
115 
116     /**
117      * Send a MPRE (Method PRofiling End) request to the client.
118      */
sendMPRE(Client client)119     public static void sendMPRE(Client client) throws IOException {
120         ByteBuffer rawBuf = allocBuffer(0);
121         JdwpPacket packet = new JdwpPacket(rawBuf);
122         ByteBuffer buf = getChunkDataBuf(rawBuf);
123 
124         // no data
125 
126         finishChunkPacket(packet, CHUNK_MPRE, buf.position());
127         Log.d("ddm-prof", "Sending " + name(CHUNK_MPRE));
128         client.sendAndConsume(packet, mInst);
129     }
130 
131     /**
132      * Handle notification that method profiling has finished writing
133      * data to disk.
134      */
handleMPRE(Client client, ByteBuffer data)135     private void handleMPRE(Client client, ByteBuffer data) {
136         byte result;
137 
138         // get the filename and make the client not have pending HPROF dump anymore.
139         String filename = client.getClientData().getPendingMethodProfiling();
140         client.getClientData().setPendingMethodProfiling(null);
141 
142         result = data.get();
143 
144         // get the app-level handler for method tracing dump
145         IMethodProfilingHandler handler = ClientData.getMethodProfilingHandler();
146         if (handler != null) {
147             if (result == 0) {
148                 handler.onSuccess(filename, client);
149 
150                 Log.d("ddm-prof", "Method profiling has finished");
151             } else {
152                 handler.onFailure(client);
153 
154                 Log.w("ddm-prof", "Method profiling has failed (check device log)");
155             }
156         }
157 
158         client.getClientData().setMethodProfilingStatus(MethodProfilingStatus.OFF);
159         client.update(Client.CHANGE_METHOD_PROFILING_STATUS);
160     }
161 
162     /**
163      * Send a MPRQ (Method PRofiling Query) request to the client.
164      */
sendMPRQ(Client client)165     public static void sendMPRQ(Client client) throws IOException {
166         ByteBuffer rawBuf = allocBuffer(0);
167         JdwpPacket packet = new JdwpPacket(rawBuf);
168         ByteBuffer buf = getChunkDataBuf(rawBuf);
169 
170         // no data
171 
172         finishChunkPacket(packet, CHUNK_MPRQ, buf.position());
173         Log.d("ddm-prof", "Sending " + name(CHUNK_MPRQ));
174         client.sendAndConsume(packet, mInst);
175     }
176 
177     /**
178      * Receive response to query.
179      */
handleMPRQ(Client client, ByteBuffer data)180     private void handleMPRQ(Client client, ByteBuffer data) {
181         byte result;
182 
183         result = data.get();
184 
185         if (result == 0) {
186             client.getClientData().setMethodProfilingStatus(MethodProfilingStatus.OFF);
187             Log.d("ddm-prof", "Method profiling is not running");
188         } else {
189             client.getClientData().setMethodProfilingStatus(MethodProfilingStatus.ON);
190             Log.d("ddm-prof", "Method profiling is running");
191         }
192         client.update(Client.CHANGE_METHOD_PROFILING_STATUS);
193     }
194 
handleFAIL(Client client, ByteBuffer data)195     private void handleFAIL(Client client, ByteBuffer data) {
196         // this can be sent if MPRS failed (like wrong permission)
197 
198         String filename = client.getClientData().getPendingMethodProfiling();
199         if (filename != null) {
200             // reset the pending file.
201             client.getClientData().setPendingMethodProfiling(null);
202 
203             // and notify of failure
204             IMethodProfilingHandler handler = ClientData.getMethodProfilingHandler();
205             if (handler != null) {
206                 handler.onFailure(client);
207             }
208 
209         }
210 
211         // send a query to know the current status
212         try {
213             sendMPRQ(client);
214         } catch (IOException e) {
215             Log.e("HandleProfiling", e);
216         }
217     }
218 }
219 
220