aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXavier Ducrohet <xav@android.com>2009-09-02 17:28:50 -0700
committerXavier Ducrohet <xav@android.com>2009-09-02 20:16:12 -0700
commitc4df663d9ecf81c50b1304b5102e54d2cd72bb5e (patch)
tree0c6804b5831f184ac845d823d6b021765c80f68c
parentd7a5dd65386ef160c848a549964140d62ce29177 (diff)
downloadsdk-c4df663d9ecf81c50b1304b5102e54d2cd72bb5e.zip
sdk-c4df663d9ecf81c50b1304b5102e54d2cd72bb5e.tar.gz
sdk-c4df663d9ecf81c50b1304b5102e54d2cd72bb5e.tar.bz2
Add support for opening HPROF files in Eclipse.
The action taken on successful HPROF dump can now be configured from the plug-in preference to be either "save to disk" or "open in eclipse". If a plug-in supporting .hprof files (such as Eclipse Memory Analyzer Tool) is present then the file will just be opened in the tool. "save to disk" does not convert the file, "open in eclipse" does convert the hprof file (using hprof-conv present in the SDK) Change-Id: Iceb347abb2af5a2979b6028c22dcbdc3bc7250ca
-rw-r--r--eclipse/features/com.android.ide.eclipse.ddms/feature.xml3
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF5
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java61
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java16
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java10
-rw-r--r--eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java99
6 files changed, 161 insertions, 33 deletions
diff --git a/eclipse/features/com.android.ide.eclipse.ddms/feature.xml b/eclipse/features/com.android.ide.eclipse.ddms/feature.xml
index c0cb12d..9b782ac 100644
--- a/eclipse/features/com.android.ide.eclipse.ddms/feature.xml
+++ b/eclipse/features/com.android.ide.eclipse.ddms/feature.xml
@@ -230,6 +230,9 @@
<import plugin="org.eclipse.ui"/>
<import plugin="org.eclipse.core.runtime"/>
<import plugin="org.eclipse.ui.console"/>
+ <import plugin="org.eclipse.core.resources"/>
+ <import plugin="org.eclipse.ui.ide"/>
+ <import plugin="org.eclipse.core.filesystem"/>
</requires>
<plugin
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
index fd818bf..3d70ec0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/META-INF/MANIFEST.MF
@@ -8,7 +8,10 @@ Bundle-Vendor: The Android Open Source Project
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
- org.eclipse.ui.console
+ org.eclipse.ui.console,
+ org.eclipse.core.resources,
+ org.eclipse.ui.ide,
+ org.eclipse.core.filesystem
Eclipse-LazyStart: true
Export-Package: com.android.ddmlib,
com.android.ddmlib.log,
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
index d559b0f..631b391 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/DdmsPlugin.java
@@ -46,6 +46,7 @@ import org.eclipse.ui.console.MessageConsoleStream;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
+import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
@@ -55,6 +56,21 @@ import java.util.Calendar;
public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeListener,
IUiSelectionListener {
+ public final static int PLATFORM_UNKNOWN = 0;
+ public final static int PLATFORM_LINUX = 1;
+ public final static int PLATFORM_WINDOWS = 2;
+ public final static int PLATFORM_DARWIN = 3;
+
+ /**
+ * Returns current platform, one of {@link #PLATFORM_WINDOWS}, {@link #PLATFORM_DARWIN},
+ * {@link #PLATFORM_LINUX} or {@link #PLATFORM_UNKNOWN}.
+ */
+ public final static int CURRENT_PLATFORM = currentPlatform();
+
+ /** hprof-conv executable (with extension for the current OS) */
+ public final static String FN_HPROF_CONVERTER = (CURRENT_PLATFORM == PLATFORM_WINDOWS) ?
+ "hprof-conv.exe" : "hprof-conv"; //$NON-NLS-1$ //$NON-NLS-2$
+
// The plug-in ID
public static final String PLUGIN_ID = "com.android.ide.eclipse.ddms"; // $NON-NLS-1$
@@ -65,12 +81,15 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL
/** Location of the adb command line executable */
private static String sAdbLocation;
+ private static String sToolsFolder;
+ private static String sHprofConverter;
/**
* Debug Launcher for already running apps
*/
private static IDebugLauncher sRunningAppDebugLauncher;
+
/** Console for DDMS log message */
private MessageConsole mDdmsConsole;
@@ -217,7 +236,7 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL
// read the adb location from the prefs to attempt to start it properly without
// having to wait for ADT to start
- sAdbLocation = eclipseStore.getString(ADB_LOCATION);
+ setAdbLocation(eclipseStore.getString(ADB_LOCATION));
// start it in a thread to return from start() asap.
new Thread() {
@@ -278,13 +297,32 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL
return sAdbLocation;
}
+ public static String getToolsFolder() {
+ return sToolsFolder;
+ }
+
+ public static String getHprofConverter() {
+ return sHprofConverter;
+ }
+
+ private static void setAdbLocation(String adbLocation) {
+ sAdbLocation = adbLocation;
+
+ File adb = new File(sAdbLocation);
+ File toolsFolder = adb.getParentFile();
+ sToolsFolder = toolsFolder.getAbsolutePath();
+
+ File hprofConverter = new File(toolsFolder, FN_HPROF_CONVERTER);
+ sHprofConverter = hprofConverter.getAbsolutePath();
+ }
+
/**
* Set the location of the adb executable and optionally starts adb
* @param adb location of adb
* @param startAdb flag to start adb
*/
public static void setAdb(String adb, boolean startAdb) {
- sAdbLocation = adb;
+ setAdbLocation(adb);
// store the location for future ddms only start.
sPlugin.getPreferenceStore().setValue(ADB_LOCATION, sAdbLocation);
@@ -562,4 +600,23 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL
}
+ /**
+ * Returns current platform
+ *
+ * @return one of {@link #PLATFORM_WINDOWS}, {@link #PLATFORM_DARWIN},
+ * {@link #PLATFORM_LINUX} or {@link #PLATFORM_UNKNOWN}.
+ */
+ public static int currentPlatform() {
+ String os = System.getProperty("os.name"); //$NON-NLS-1$
+ if (os.startsWith("Mac OS")) { //$NON-NLS-1$
+ return PLATFORM_DARWIN;
+ } else if (os.startsWith("Windows")) { //$NON-NLS-1$
+ return PLATFORM_WINDOWS;
+ } else if (os.startsWith("Linux")) { //$NON-NLS-1$
+ return PLATFORM_LINUX;
+ }
+
+ return PLATFORM_UNKNOWN;
+ }
+
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
index b53d85c..4f91da0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
@@ -17,6 +17,7 @@
package com.android.ide.eclipse.ddms.preferences;
import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.views.DeviceView.HProfHandler;
import com.android.ddmlib.DdmPreferences;
import com.android.ddmuilib.DdmUiPreferences;
@@ -29,7 +30,7 @@ import org.eclipse.swt.graphics.FontData;
* Class used to initialize default preference values.
*/
public class PreferenceInitializer extends AbstractPreferenceInitializer {
-
+
public final static String ATTR_LOG_LEVEL =
DdmsPlugin.PLUGIN_ID + ".logLevel"; //$NON-NLS-1$
@@ -56,7 +57,10 @@ public class PreferenceInitializer extends AbstractPreferenceInitializer {
public final static String ATTR_LOGCAT_FONT =
DdmsPlugin.PLUGIN_ID + ".logcatFont"; //$NON-NLS-1$
-
+
+ public final static String ATTR_HPROF_ACTION =
+ DdmsPlugin.PLUGIN_ID + ".hprofAction"; //$NON-NLS-1$
+
/*
* (non-Javadoc)
*
@@ -84,14 +88,16 @@ public class PreferenceInitializer extends AbstractPreferenceInitializer {
store.setDefault(ATTR_LOGCAT_FONT,
new FontData("Courier", 10, SWT.NORMAL).toString()); //$NON-NLS-1$
+
+ store.setDefault(ATTR_HPROF_ACTION, HProfHandler.ACTION_OPEN);
}
-
+
/**
- * Initializes the preferences of ddmlib and ddmuilib with values from the eclipse store.
+ * Initializes the preferences of ddmlib and ddmuilib with values from the eclipse store.
*/
public synchronized static void setupPreferences() {
IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
-
+
DdmPreferences.setDebugPortBase(store.getInt(ATTR_DEBUG_PORT_BASE));
DdmPreferences.setSelectedDebugPort(store.getInt(ATTR_SELECTED_DEBUG_PORT));
DdmPreferences.setLogLevel(store.getString(ATTR_LOG_LEVEL));
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java
index 86e87c7..87addf6 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferencePage.java
@@ -17,10 +17,12 @@
package com.android.ide.eclipse.ddms.preferences;
import com.android.ide.eclipse.ddms.DdmsPlugin;
+import com.android.ide.eclipse.ddms.views.DeviceView.HProfHandler;
import com.android.ddmlib.Log.LogLevel;
import com.android.ddmuilib.PortFieldEditor;
import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.ComboFieldEditor;
import org.eclipse.jface.preference.FieldEditorPreferencePage;
import org.eclipse.jface.preference.IntegerFieldEditor;
import org.eclipse.jface.preference.RadioGroupFieldEditor;
@@ -63,6 +65,13 @@ public class PreferencePage extends FieldEditorPreferencePage implements
ife.setValidRange(1, 60);
addField(ife);
+ ComboFieldEditor cfe = new ComboFieldEditor(PreferenceInitializer.ATTR_HPROF_ACTION,
+ "HPROF Action:", new String[][] {
+ { "Save to disk", HProfHandler.ACTION_SAVE },
+ { "Open in Eclipse", HProfHandler.ACTION_OPEN },
+ }, getFieldEditorParent());
+ addField(cfe);
+
RadioGroupFieldEditor rgfe = new RadioGroupFieldEditor(PreferenceInitializer.ATTR_LOG_LEVEL,
"Logging Level", 1, new String[][] {
{ "Verbose", LogLevel.VERBOSE.getStringValue() },
@@ -74,7 +83,6 @@ public class PreferencePage extends FieldEditorPreferencePage implements
},
getFieldEditorParent(), true);
addField(rgfe);
-
}
public void init(IWorkbench workbench) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
index 7f9c3c8..50eee26 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/views/DeviceView.java
@@ -30,8 +30,12 @@ import com.android.ddmuilib.SyncProgressMonitor;
import com.android.ddmuilib.DevicePanel.IUiSelectionListener;
import com.android.ide.eclipse.ddms.DdmsPlugin;
import com.android.ide.eclipse.ddms.DdmsPlugin.IDebugLauncher;
+import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer;
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuManager;
@@ -40,6 +44,7 @@ import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
@@ -47,10 +52,14 @@ import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;
import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
public class DeviceView extends ViewPart implements IUiSelectionListener {
@@ -72,11 +81,15 @@ public class DeviceView extends ViewPart implements IUiSelectionListener {
private Action mHprofAction;
private IDebugLauncher mDebugLauncher;
- private class HProfHandler implements IHprofDumpHandler {
+ public class HProfHandler implements IHprofDumpHandler {
+ public final static String ACTION_SAVE ="hprof.save"; //$NON-NLS-1$
+ public final static String ACTION_OPEN = "hprof.open"; //$NON-NLS-1$
+
+ public final static String DOT_HPROF = ".hprof"; //$NON-NLS-1$
private final Shell mParentShell;
- public HProfHandler(Shell parentShell) {
+ HProfHandler(Shell parentShell) {
mParentShell = parentShell;
}
@@ -98,7 +111,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener {
});
}
- public void onSuccess(final String file, final Client client) {
+ public void onSuccess(final String remoteFile, final Client client) {
mParentShell.getDisplay().asyncExec(new Runnable() {
public void run() {
final IDevice device = client.getDevice();
@@ -106,7 +119,19 @@ public class DeviceView extends ViewPart implements IUiSelectionListener {
// get the sync service to pull the HPROF file
final SyncService sync = client.getDevice().getSyncService();
if (sync != null) {
- promptAndPull(device, client, sync, file);
+ // get from the preference what action to take
+ IPreferenceStore store = DdmsPlugin.getDefault().getPreferenceStore();
+ String value = store.getString(PreferenceInitializer.ATTR_HPROF_ACTION);
+ if (ACTION_OPEN.equals(value)) {
+ File temp = File.createTempFile("android", DOT_HPROF); //$NON-NLS-1$
+ String tempPath = temp.getAbsolutePath();
+ pull(sync, tempPath, remoteFile);
+
+ open(tempPath);
+ } else {
+ // default action is ACTION_SAVE
+ promptAndPull(device, client, sync, remoteFile);
+ }
} else {
MessageDialog.openError(mParentShell, "HPROF Error",
String.format(
@@ -134,29 +159,11 @@ public class DeviceView extends ViewPart implements IUiSelectionListener {
fileDialog.setText("Save HPROF file");
fileDialog.setFileName(
- client.getClientData().getClientDescription() + ".hprof");
+ client.getClientData().getClientDescription() + DOT_HPROF);
final String localFileName = fileDialog.open();
if (localFileName != null) {
- final File localFile = new File(localFileName);
-
- new ProgressMonitorDialog(mParentShell).run(true, true,
- new IRunnableWithProgress() {
- public void run(IProgressMonitor monitor) {
- SyncResult result = sync.pullFile(remoteFile, localFileName,
- new SyncProgressMonitor(monitor, String.format(
- "Pulling %1$s from the device",
- localFile.getName())));
-
- if (result.getCode() != SyncService.RESULT_OK) {
- MessageDialog.openError(mParentShell, "HPROF Error",
- String.format("Failed to pull %1$s: %2$s", remoteFile,
- result.getMessage()));
- }
-
- sync.close();
- }
- });
+ pull(sync, localFileName, remoteFile);
}
} catch (Exception e) {
MessageDialog.openError(mParentShell, "HPROF Error",
@@ -164,6 +171,50 @@ public class DeviceView extends ViewPart implements IUiSelectionListener {
device.getSerialNumber()));
}
}
+
+ private void pull(final SyncService sync,
+ final String localFileName, final String remoteFile)
+ throws InvocationTargetException, InterruptedException {
+ new ProgressMonitorDialog(mParentShell).run(true, true,
+ new IRunnableWithProgress() {
+ public void run(IProgressMonitor monitor) {
+ SyncResult result = sync.pullFile(remoteFile, localFileName,
+ new SyncProgressMonitor(monitor, String.format(
+ "Pulling %1$s from the device",
+ remoteFile)));
+
+ if (result.getCode() != SyncService.RESULT_OK) {
+ MessageDialog.openError(mParentShell, "HPROF Error",
+ String.format("Failed to pull %1$s: %2$s", remoteFile,
+ result.getMessage()));
+ }
+
+ sync.close();
+ }
+ });
+ }
+
+ private void open(String path) throws IOException, InterruptedException, PartInitException {
+ // make a temp file to convert the hprof into something
+ // readable by normal tools
+ File temp = File.createTempFile("android", DOT_HPROF);
+ String tempPath = temp.getAbsolutePath();
+
+ String[] command = new String[3];
+ command[0] = DdmsPlugin.getHprofConverter();
+ command[1] = path;
+ command[2] = tempPath;
+
+ Process p = Runtime.getRuntime().exec(command);
+ p.waitFor();
+
+ IFileStore fileStore = EFS.getLocalFileSystem().getStore(new Path(tempPath));
+ if (!fileStore.fetchInfo().isDirectory() && fileStore.fetchInfo().exists()) {
+ IDE.openEditorOnFileStore(
+ getSite().getWorkbenchWindow().getActivePage(),
+ fileStore);
+ }
+ }
}