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.ddmuilib.handler; 18 19 import com.android.ddmlib.Client; 20 import com.android.ddmlib.ClientData.IMethodProfilingHandler; 21 import com.android.ddmlib.DdmConstants; 22 import com.android.ddmlib.IDevice; 23 import com.android.ddmlib.Log; 24 import com.android.ddmlib.SyncException; 25 import com.android.ddmlib.SyncService; 26 import com.android.ddmlib.SyncService.ISyncProgressMonitor; 27 import com.android.ddmlib.TimeoutException; 28 import com.android.ddmuilib.DdmUiPreferences; 29 import com.android.ddmuilib.SyncProgressHelper; 30 import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; 31 import com.android.ddmuilib.console.DdmConsole; 32 33 import org.eclipse.swt.widgets.Shell; 34 35 import java.io.BufferedReader; 36 import java.io.File; 37 import java.io.IOException; 38 import java.io.InputStreamReader; 39 import java.lang.reflect.InvocationTargetException; 40 41 /** 42 * Handler for Method tracing. 43 * This will pull the trace file into a temp file and launch traceview. 44 */ 45 public class MethodProfilingHandler extends BaseFileHandler 46 implements IMethodProfilingHandler { 47 MethodProfilingHandler(Shell parentShell)48 public MethodProfilingHandler(Shell parentShell) { 49 super(parentShell); 50 } 51 52 @Override getDialogTitle()53 protected String getDialogTitle() { 54 return "Method Profiling Error"; 55 } 56 onStartFailure(final Client client, final String message)57 public void onStartFailure(final Client client, final String message) { 58 displayErrorInUiThread( 59 "Unable to create Method Profiling file for application '%1$s'\n\n%2$s" + 60 "Check logcat for more information.", 61 client.getClientData().getClientDescription(), 62 message != null ? message + "\n\n" : ""); 63 } 64 onEndFailure(final Client client, final String message)65 public void onEndFailure(final Client client, final String message) { 66 displayErrorInUiThread( 67 "Unable to finish Method Profiling for application '%1$s'\n\n%2$s" + 68 "Check logcat for more information.", 69 client.getClientData().getClientDescription(), 70 message != null ? message + "\n\n" : ""); 71 } 72 onSuccess(final String remoteFilePath, final Client client)73 public void onSuccess(final String remoteFilePath, final Client client) { 74 mParentShell.getDisplay().asyncExec(new Runnable() { 75 public void run() { 76 if (remoteFilePath == null) { 77 displayErrorFromUiThread( 78 "Unable to download trace file: unknown file name.\n" + 79 "This can happen if you disconnected the device while recording the trace."); 80 return; 81 } 82 83 final IDevice device = client.getDevice(); 84 try { 85 // get the sync service to pull the HPROF file 86 final SyncService sync = client.getDevice().getSyncService(); 87 if (sync != null) { 88 pullAndOpen(sync, remoteFilePath); 89 } else { 90 displayErrorFromUiThread( 91 "Unable to download trace file from device '%1$s'.", 92 device.getSerialNumber()); 93 } 94 } catch (Exception e) { 95 displayErrorFromUiThread("Unable to download trace file from device '%1$s'.", 96 device.getSerialNumber()); 97 } 98 } 99 100 }); 101 } 102 onSuccess(byte[] data, final Client client)103 public void onSuccess(byte[] data, final Client client) { 104 try { 105 File tempFile = saveTempFile(data, DdmConstants.DOT_TRACE); 106 open(tempFile.getAbsolutePath()); 107 } catch (IOException e) { 108 String errorMsg = e.getMessage(); 109 displayErrorInUiThread( 110 "Failed to save trace data into temp file%1$s", 111 errorMsg != null ? ":\n" + errorMsg : "."); 112 } 113 } 114 115 /** 116 * pulls and open a file. This is run from the UI thread. 117 */ pullAndOpen(final SyncService sync, final String remoteFilePath)118 private void pullAndOpen(final SyncService sync, final String remoteFilePath) 119 throws InvocationTargetException, InterruptedException, IOException { 120 // get a temp file 121 File temp = File.createTempFile("android", DdmConstants.DOT_TRACE); //$NON-NLS-1$ 122 final String tempPath = temp.getAbsolutePath(); 123 124 // pull the file 125 try { 126 SyncProgressHelper.run(new SyncRunnable() { 127 public void run(ISyncProgressMonitor monitor) 128 throws SyncException, IOException, TimeoutException { 129 sync.pullFile(remoteFilePath, tempPath, monitor); 130 } 131 132 public void close() { 133 sync.close(); 134 } 135 }, 136 String.format("Pulling %1$s from the device", remoteFilePath), mParentShell); 137 138 // open the temp file in traceview 139 open(tempPath); 140 } catch (SyncException e) { 141 if (e.wasCanceled() == false) { 142 displayErrorFromUiThread("Unable to download trace file:\n\n%1$s", e.getMessage()); 143 } 144 } catch (TimeoutException e) { 145 displayErrorFromUiThread("Unable to download trace file:\n\ntimeout"); 146 } 147 } 148 open(String tempPath)149 protected void open(String tempPath) { 150 // now that we have the file, we need to launch traceview 151 String[] command = new String[2]; 152 command[0] = DdmUiPreferences.getTraceview(); 153 command[1] = tempPath; 154 155 try { 156 final Process p = Runtime.getRuntime().exec(command); 157 158 // create a thread for the output 159 new Thread("Traceview output") { 160 @Override 161 public void run() { 162 // create a buffer to read the stderr output 163 InputStreamReader is = new InputStreamReader(p.getErrorStream()); 164 BufferedReader resultReader = new BufferedReader(is); 165 166 // read the lines as they come. if null is returned, it's 167 // because the process finished 168 try { 169 while (true) { 170 String line = resultReader.readLine(); 171 if (line != null) { 172 DdmConsole.printErrorToConsole("Traceview: " + line); 173 } else { 174 break; 175 } 176 } 177 // get the return code from the process 178 p.waitFor(); 179 } catch (Exception e) { 180 Log.e("traceview", e); 181 } 182 } 183 }.start(); 184 } catch (IOException e) { 185 Log.e("traceview", e); 186 } 187 } 188 } 189