/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.ddmuilib.handler; import com.android.ddmlib.Client; import com.android.ddmlib.DdmConstants; import com.android.ddmlib.IDevice; import com.android.ddmlib.Log; import com.android.ddmlib.SyncException; import com.android.ddmlib.SyncService; import com.android.ddmlib.TimeoutException; import com.android.ddmlib.ClientData.IMethodProfilingHandler; import com.android.ddmlib.SyncService.ISyncProgressMonitor; import com.android.ddmuilib.DdmUiPreferences; import com.android.ddmuilib.SyncProgressHelper; import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; import com.android.ddmuilib.console.DdmConsole; import org.eclipse.swt.widgets.Shell; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.InvocationTargetException; /** * Handler for Method tracing. * This will pull the trace file into a temp file and launch traceview. */ public class MethodProfilingHandler extends BaseFileHandler implements IMethodProfilingHandler { public MethodProfilingHandler(Shell parentShell) { super(parentShell); } @Override protected String getDialogTitle() { return "Method Profiling Error"; } public void onStartFailure(final Client client, final String message) { displayErrorInUiThread( "Unable to create Method Profiling file for application '%1$s'\n\n%2$s" + "Check logcat for more information.", client.getClientData().getClientDescription(), message != null ? message + "\n\n" : ""); } public void onEndFailure(final Client client, final String message) { displayErrorInUiThread( "Unable to finish Method Profiling for application '%1$s'\n\n%2$s" + "Check logcat for more information.", client.getClientData().getClientDescription(), message != null ? message + "\n\n" : ""); } public void onSuccess(final String remoteFilePath, final Client client) { mParentShell.getDisplay().asyncExec(new Runnable() { public void run() { if (remoteFilePath == null) { displayErrorFromUiThread( "Unable to download trace file: unknown file name.\n" + "This can happen if you disconnected the device while recording the trace."); return; } final IDevice device = client.getDevice(); try { // get the sync service to pull the HPROF file final SyncService sync = client.getDevice().getSyncService(); if (sync != null) { pullAndOpen(sync, remoteFilePath); } else { displayErrorFromUiThread( "Unable to download trace file from device '%1$s'.", device.getSerialNumber()); } } catch (Exception e) { displayErrorFromUiThread("Unable to download trace file from device '%1$s'.", device.getSerialNumber()); } } }); } public void onSuccess(byte[] data, final Client client) { try { File tempFile = saveTempFile(data, DdmConstants.DOT_TRACE); open(tempFile.getAbsolutePath()); } catch (IOException e) { String errorMsg = e.getMessage(); displayErrorInUiThread( "Failed to save trace data into temp file%1$s", errorMsg != null ? ":\n" + errorMsg : "."); } } /** * pulls and open a file. This is run from the UI thread. */ private void pullAndOpen(final SyncService sync, final String remoteFilePath) throws InvocationTargetException, InterruptedException, IOException { // get a temp file File temp = File.createTempFile("android", DdmConstants.DOT_TRACE); //$NON-NLS-1$ final String tempPath = temp.getAbsolutePath(); // pull the file try { SyncProgressHelper.run(new SyncRunnable() { public void run(ISyncProgressMonitor monitor) throws SyncException, IOException, TimeoutException { sync.pullFile(tempPath, remoteFilePath, monitor); } public void close() { sync.close(); } }, String.format("Pulling %1$s from the device", remoteFilePath), mParentShell); // open the temp file in traceview open(tempPath); } catch (SyncException e) { if (e.wasCanceled() == false) { displayErrorFromUiThread("Unable to download trace file:\n\n%1$s", e.getMessage()); } } catch (TimeoutException e) { displayErrorFromUiThread("Unable to download trace file:\n\ntimeout"); } } protected void open(String tempPath) { // now that we have the file, we need to launch traceview String[] command = new String[2]; command[0] = DdmUiPreferences.getTraceview(); command[1] = tempPath; try { final Process p = Runtime.getRuntime().exec(command); // create a thread for the output new Thread("Traceview output") { @Override public void run() { // create a buffer to read the stderr output InputStreamReader is = new InputStreamReader(p.getErrorStream()); BufferedReader resultReader = new BufferedReader(is); // read the lines as they come. if null is returned, it's // because the process finished try { while (true) { String line = resultReader.readLine(); if (line != null) { DdmConsole.printErrorToConsole("Traceview: " + line); } else { break; } } // get the return code from the process p.waitFor(); } catch (Exception e) { Log.e("traceview", e); } } }.start(); } catch (IOException e) { Log.e("traceview", e); } } }