diff options
author | Xavier Ducrohet <xav@android.com> | 2010-09-07 15:54:35 -0700 |
---|---|---|
committer | Xavier Ducrohet <xav@android.com> | 2010-09-07 16:02:33 -0700 |
commit | 0662cb950e8e8a5e33ef8a6870f331d5ea452e1d (patch) | |
tree | bef90938b1b981603160d7d9a89ac3e8ecaefb1d | |
parent | d1db7e2ce68f42fafa916d4b0d9f2a50f946b980 (diff) | |
download | sdk-0662cb950e8e8a5e33ef8a6870f331d5ea452e1d.zip sdk-0662cb950e8e8a5e33ef8a6870f331d5ea452e1d.tar.gz sdk-0662cb950e8e8a5e33ef8a6870f331d5ea452e1d.tar.bz2 |
New extension points for DDMS
debugger connector is used by the "debug running app" button in the
device list view.
source revealer is used by the thread panel when double clicking
on an entry of the stack trace.
Change-Id: Ida07617a24d37f1d769d86859fd35d5bb19f5fd2
15 files changed, 570 insertions, 148 deletions
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml index bb30ec0..e6a5e82 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.adt/plugin.xml @@ -771,4 +771,16 @@ class="com.android.ide.eclipse.adt.AdbLocator"> </locator> </extension> + <extension + point="com.android.ide.eclipse.ddms.debuggerConnector"> + <connector + class="com.android.ide.eclipse.adt.DebuggerConnector"> + </connector> + </extension> + <extension + point="com.android.ide.eclipse.ddms.sourceRevealer"> + <revealer + class="com.android.ide.eclipse.adt.SourceRevealer"> + </revealer> + </extension> </plugin> diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java index b45b192..9c87f26 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdbLocator.java @@ -18,6 +18,10 @@ package com.android.ide.eclipse.adt; import com.android.ide.eclipse.ddms.IAdbLocator; +/** + * Implementation of the com.android.ide.ddms.adbLocator extension point. + * + */ public class AdbLocator implements IAdbLocator { public String getAdbLocation() { diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java index eee0bf1..c2088df 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/AdtPlugin.java @@ -26,7 +26,6 @@ import com.android.ide.eclipse.adt.internal.editors.layout.LayoutEditor; import com.android.ide.eclipse.adt.internal.editors.menu.MenuEditor; import com.android.ide.eclipse.adt.internal.editors.resources.ResourcesEditor; import com.android.ide.eclipse.adt.internal.editors.xml.XmlEditor; -import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchController; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs; import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs.BuildVerbosity; import com.android.ide.eclipse.adt.internal.project.AndroidClasspathContainerInitializer; @@ -247,50 +246,6 @@ public class AdtPlugin extends AbstractUIPlugin { // check the location of SDK final boolean isSdkLocationValid = checkSdkLocationAndId(); - // and give it the debug launcher for android projects - DdmsPlugin.setRunningAppDebugLauncher(new DdmsPlugin.IDebugLauncher() { - public boolean debug(String appName, int port) { - // search for an android project matching the process name - IProject project = ProjectHelper.findAndroidProjectByAppName(appName); - if (project != null) { - AndroidLaunchController.debugRunningApp(project, port); - return true; - } else { - // check to see if there's a platform project defined by an env var. - String var = System.getenv("ANDROID_PLATFORM_PROJECT"); //$NON-NLS-1$ - if (var != null && var.length() > 0) { - boolean auto = "AUTO".equals(var); //$NON-NLS-1$ - - // Get the list of project for the current workspace - IWorkspace workspace = ResourcesPlugin.getWorkspace(); - IProject[] projects = workspace.getRoot().getProjects(); - - // look for a project that matches the env var or take the first - // one if in automatic mode. - for (IProject p : projects) { - if (p.isOpen()) { - if (auto || p.getName().equals(var)) { - AndroidLaunchController.debugRunningApp(p, port); - return true; - } - } - } - - } - return false; - } - } - }); - - StackTracePanel.setSourceRevealer(new ISourceRevealer() { - public void reveal(String applicationName, String className, int line) { - IProject project = ProjectHelper.findAndroidProjectByAppName(applicationName); - if (project != null) { - BaseProjectHelper.revealSource(project, className, line); - } - } - }); - // initialize editors startEditors(); diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/DebuggerConnector.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/DebuggerConnector.java new file mode 100644 index 0000000..35da340 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/DebuggerConnector.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.ide.eclipse.adt; + +import com.android.ide.eclipse.adt.internal.launch.AndroidLaunchController; +import com.android.ide.eclipse.adt.internal.project.ProjectHelper; +import com.android.ide.eclipse.ddms.IDebuggerConnector; + +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.ResourcesPlugin; + +/** + * Implementation of the com.android.ide.ddms.debuggerConnector extension point. + */ +public class DebuggerConnector implements IDebuggerConnector { + + public boolean connectDebugger(String appName, int port) { + // search for an android project matching the process name + IProject project = ProjectHelper.findAndroidProjectByAppName(appName); + if (project != null) { + AndroidLaunchController.debugRunningApp(project, port); + return true; + } else { + // check to see if there's a platform project defined by an env var. + String var = System.getenv("ANDROID_PLATFORM_PROJECT"); //$NON-NLS-1$ + if (var != null && var.length() > 0) { + boolean auto = "AUTO".equals(var); //$NON-NLS-1$ + + // Get the list of project for the current workspace + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + IProject[] projects = workspace.getRoot().getProjects(); + + // look for a project that matches the env var or take the first + // one if in automatic mode. + for (IProject p : projects) { + if (p.isOpen()) { + if (auto || p.getName().equals(var)) { + AndroidLaunchController.debugRunningApp(p, port); + return true; + } + } + } + + } + return false; + } + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java new file mode 100644 index 0000000..2e2924c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/SourceRevealer.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php + * + * 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.ide.eclipse.adt; + +import com.android.ide.eclipse.adt.internal.project.BaseProjectHelper; +import com.android.ide.eclipse.adt.internal.project.ProjectHelper; +import com.android.ide.eclipse.ddms.ISourceRevealer; + +import org.eclipse.core.resources.IProject; + +/** + * Implementation of the com.android.ide.ddms.sourceRevealer extension point. + * + */ +public class SourceRevealer implements ISourceRevealer { + + public boolean reveal(String applicationName, String className, int line) { + IProject project = ProjectHelper.findAndroidProjectByAppName(applicationName); + if (project != null) { + return BaseProjectHelper.revealSource(project, className, line); + } + + return false; + } +} diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java index 2eb5dd2..49a44d6 100644 --- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java +++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/project/BaseProjectHelper.java @@ -305,10 +305,17 @@ public final class BaseProjectHelper { * @param project * @param className * @param line + * @return true if the source was revealed */ - public static void revealSource(IProject project, String className, int line) { - // in case the type is enclosed, we need to replace the $ with . - className = className.replaceAll("\\$", "\\."); //$NON-NLS-1$ //$NON-NLS2$ + public static boolean revealSource(IProject project, String className, int line) { + // Inner classes are pointless: All we need is the enclosing type to find the file, and the + // line number. + // Since the anonymous ones will cause IJavaProject#findType to fail, we remove + // all of them. + int pos = className.indexOf('$'); + if (pos != -1) { + className = className.substring(0, pos); + } // get the java project IJavaProject javaProject = JavaCore.create(project); @@ -342,11 +349,15 @@ public final class BaseProjectHelper { // select and reveal the line. textEditor.selectAndReveal(lineInfo.getOffset(), lineInfo.getLength()); } + + return true; } } catch (JavaModelException e) { } catch (PartInitException e) { } catch (BadLocationException e) { } + + return false; } /** diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml index d0fe8af..4fe6786 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/plugin.xml @@ -2,6 +2,9 @@ <?eclipse version="3.2"?> <plugin> <extension-point id="adbLocator" name="ADB Locator" schema="schema/adbLocator.exsd"/> + <extension-point id="debuggerConnector" name="Debugger Connector" schema="schema/debuggerConnector.exsd"/> + <extension-point id="sourceRevealer" name="Source Revealer" schema="schema/sourceRevealer.exsd"/> + <extension point="org.eclipse.ui.views"> <category diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd index 6292ec1..e2c246c 100644 --- a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/adbLocator.exsd @@ -6,7 +6,7 @@ <meta.schema plugin="com.android.ide.eclipse.ddms" id="adbLocator" name="ADB Locator"/> </appInfo> <documentation> - Extension to provide the location of adb to DDMS. + Extension Point to provide the location of adb to DDMS. </documentation> </annotation> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/debuggerConnector.exsd b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/debuggerConnector.exsd new file mode 100644 index 0000000..515713a --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/debuggerConnector.exsd @@ -0,0 +1,104 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="com.android.ide.eclipse.ddms" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="com.android.ide.eclipse.ddms" id="debuggerConnector" name="Debugger Connector"/> + </appInfo> + <documentation> + Extension Point to provide a way to connect a debugger to a VM running on a connected device. + +The goal of the extension is to identify which project in the workspace matches the running application to properly setup a launch configuration. + </documentation> + </annotation> + + <element name="connector"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn=":com.android.ide.eclipse.ddms.IDebuggerConnector"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence> + <element ref="connector"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 8.0.0 + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="examples"/> + </appInfo> + <documentation> + [Enter extension point usage example here.] + </documentation> + </annotation> + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + The class must implement com.android.ide.ddms.IDebuggerConnector. + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (C) 2010 The Android Open Source Project + </documentation> + </annotation> + +</schema> diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/schema/sourceRevealer.exsd b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/sourceRevealer.exsd new file mode 100644 index 0000000..9f2cf9c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/schema/sourceRevealer.exsd @@ -0,0 +1,96 @@ +<?xml version='1.0' encoding='UTF-8'?> +<!-- Schema file written by PDE --> +<schema targetNamespace="com.android.ide.eclipse.ddms" xmlns="http://www.w3.org/2001/XMLSchema"> +<annotation> + <appInfo> + <meta.schema plugin="com.android.ide.eclipse.ddms" id="sourceRevealer" name="Source Revealer"/> + </appInfo> + <documentation> + Extension Point to provide a way to display the source code of a VM running on a connected device. + +The goal of the extension is to identify which project in the workspace matches the running application to properly identify the source file to open. + </documentation> + </annotation> + + <element name="revealer"> + <complexType> + <attribute name="class" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute kind="java" basedOn=":com.android.ide.eclipse.ddms.ISourceRevealer"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <element name="extension"> + <annotation> + <appInfo> + <meta.element /> + </appInfo> + </annotation> + <complexType> + <sequence> + <element ref="revealer"/> + </sequence> + <attribute name="point" type="string" use="required"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="id" type="string"> + <annotation> + <documentation> + + </documentation> + </annotation> + </attribute> + <attribute name="name" type="string"> + <annotation> + <documentation> + + </documentation> + <appInfo> + <meta.attribute translatable="true"/> + </appInfo> + </annotation> + </attribute> + </complexType> + </element> + + <annotation> + <appInfo> + <meta.section type="since"/> + </appInfo> + <documentation> + 8.0.0 + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="apiinfo"/> + </appInfo> + <documentation> + The class must implement com.android.ide.ddms.ISourceRevealer. + </documentation> + </annotation> + + + <annotation> + <appInfo> + <meta.section type="copyright"/> + </appInfo> + <documentation> + Copyright (C) 2010 The Android Open Source Project + </documentation> + </annotation> + +</schema> 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 3a99459..26ccbe8 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 @@ -26,9 +26,9 @@ import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener; import com.android.ddmlib.Log.ILogOutput; import com.android.ddmlib.Log.LogLevel; import com.android.ddmuilib.DdmUiPreferences; +import com.android.ddmuilib.StackTracePanel; import com.android.ddmuilib.DevicePanel.IUiSelectionListener; import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer; -import com.android.ide.eclipse.ddms.views.DeviceView; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; @@ -63,7 +63,7 @@ import java.util.Calendar; * The activator class controls the plug-in life cycle */ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeListener, - IUiSelectionListener { + IUiSelectionListener, com.android.ddmuilib.StackTracePanel.ISourceRevealer { // The plug-in ID @@ -77,10 +77,11 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL private static String sToolsFolder; private static String sHprofConverter; - /** - * Debug Launcher for already running apps + /** debugger connectors for already running apps. + * Initialized from an extension point. */ - private static IDebugLauncher sRunningAppDebugLauncher; + private IDebuggerConnector[] mDebuggerConnectors; + private ISourceRevealer[] mSourceRevealers; /** Console for DDMS log message */ @@ -94,12 +95,6 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL private Color mRed; - /** - * Interface to provide debugger launcher for running apps. - */ - public interface IDebugLauncher { - public boolean debug(String packageName, int port); - } /** * Classes which implement this interface provide methods that deals @@ -221,47 +216,136 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL } }); - // start it in a thread to return from start() asap. - new Job("ADB location resolution") { + // do some last initializations + + // set the preferences. + PreferenceInitializer.setupPreferences(); + + // init the lib + AndroidDebugBridge.init(true /* debugger support */); + + // get the available adb locators + final IAdbLocator[] locators = findAdbLocators(); + + // Find the location of ADB. + // Because the running the locators will initialize their plug-in, we do this in a job + // to make sure that the init of the DDMS plug-in is finished. Otherwise, if another + // plug-in uses DDMS classes in their start() method, this would fail since DDMS would not + // be loaded yet. + // The job is scheduled at the end of the + Job adbLocatorJob = new Job("ADB Location resolution") { @Override protected IStatus run(IProgressMonitor monitor) { - // set the preferences. - PreferenceInitializer.setupPreferences(); - - // init the lib - AndroidDebugBridge.init(true /* debugger support */); - - // get the adb location from an implementation of the ADB Locator extension point. - IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); - IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( - "com.android.ide.eclipse.ddms.adbLocator"); //$NON-NLS-1$ - IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); - if (configElements.length > 0) { - // only use the first one, ignore the others. - IConfigurationElement configElement = configElements[0]; - - // instantiate the clas - try { - Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ - if (obj instanceof IAdbLocator) { - String adbLocation = ((IAdbLocator) obj).getAdbLocation(); - if (adbLocation != null) { - if (setAdbLocation(adbLocation)) { - AndroidDebugBridge.createBridge(sAdbLocation, - true /* forceNewBridge */); - } + for (IAdbLocator locator : locators) { + String adbLocation = locator.getAdbLocation(); + if (adbLocation != null) { + // checks if the location is valid. + if (setAdbLocation(adbLocation)) { + AndroidDebugBridge.createBridge(sAdbLocation, + true /* forceNewBridge */); - } + // no need to look at the other locators. + break; } - } catch (CoreException e) { - return e.getStatus(); } } - return Status.OK_STATUS; } + }; + + // get the available debugger connectors + mDebuggerConnectors = findDebuggerConnectors(); + + // get the available source revealer + mSourceRevealers = findSourceRevealers(); + // this class is set as the main source revealer and will look at all the implementations + // of the extension point. see #reveal(String, String, int) + StackTracePanel.setSourceRevealer(this); + + // finish the method with the schedule of the adbLocator job since it must run after + // this method ends. + adbLocatorJob.schedule(); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point called adbLocator. + * + * @return an array of all locators found, or an empty array if none were found. + */ + private IAdbLocator[] findAdbLocators() throws CoreException { + ArrayList<IAdbLocator> list = new ArrayList<IAdbLocator>(); + + // get the adb location from an implementation of the ADB Locator extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( + "com.android.ide.eclipse.ddms.adbLocator"); //$NON-NLS-1$ + IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the clas + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof IAdbLocator) { + list.add((IAdbLocator) obj); + } + } + + return list.toArray(new IAdbLocator[list.size()]); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point called debuggerConnector. + * + * @return an array of all locators found, or an empty array if none were found. + */ + private IDebuggerConnector[] findDebuggerConnectors() throws CoreException { + ArrayList<IDebuggerConnector> list = new ArrayList<IDebuggerConnector>(); + + // get the adb location from an implementation of the ADB Locator extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( + "com.android.ide.eclipse.ddms.debuggerConnector"); //$NON-NLS-1$ + IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the clas + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof IDebuggerConnector) { + list.add((IDebuggerConnector) obj); + } + } + + return list.toArray(new IDebuggerConnector[list.size()]); + } + + /** + * Finds if any other plug-in is extending the exposed Extension Point called sourceRevealer. + * + * @return an array of all locators found, or an empty array if none were found. + */ + private ISourceRevealer[] findSourceRevealers() throws CoreException { + ArrayList<ISourceRevealer> list = new ArrayList<ISourceRevealer>(); + + // get the adb location from an implementation of the ADB Locator extension point. + IExtensionRegistry extensionRegistry = Platform.getExtensionRegistry(); + IExtensionPoint extensionPoint = extensionRegistry.getExtensionPoint( + "com.android.ide.eclipse.ddms.sourceRevealer"); //$NON-NLS-1$ + IConfigurationElement[] configElements = extensionPoint.getConfigurationElements(); + if (configElements.length > 0) { + // only use the first one, ignore the others. + IConfigurationElement configElement = configElements[0]; + + // instantiate the clas + Object obj = configElement.createExecutableExtension("class"); //$NON-NLS-1$ + if (obj instanceof ISourceRevealer) { + list.add((ISourceRevealer) obj); + } + } - }.schedule(); + return list.toArray(new ISourceRevealer[list.size()]); } public static Display getDisplay() { @@ -357,31 +441,8 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL } } - /** - * Sets the launcher responsible for connecting the debugger to running applications. - * @param launcher The launcher. - */ - public static void setRunningAppDebugLauncher(IDebugLauncher launcher) { - sRunningAppDebugLauncher = launcher; - - // if the process view is already running, give it the launcher. - // This method could be called from a non ui thread, so we make sure to do that - // in the ui thread. - Display display = getDisplay(); - if (display != null && display.isDisposed() == false) { - display.asyncExec(new Runnable() { - public void run() { - DeviceView dv = DeviceView.getInstance(); - if (dv != null) { - dv.setDebugLauncher(sRunningAppDebugLauncher); - } - } - }); - } - } - - public static IDebugLauncher getRunningAppDebugLauncher() { - return sRunningAppDebugLauncher; + public IDebuggerConnector[] getDebuggerConnectors() { + return mDebuggerConnectors; } public synchronized void addSelectionListener(ISelectionListener listener) { @@ -601,4 +662,16 @@ public final class DdmsPlugin extends AbstractUIPlugin implements IDeviceChangeL return String.format("[%1$tF %1$tT - %2$s]", c, tag); } + + /** + * Implementation of com.android.ddmuilib.StackTracePanel.ISourceRevealer. + */ + public void reveal(String applicationName, String className, int line) { + // loop on all source revealer till one succeeds + for (ISourceRevealer revealer : mSourceRevealers) { + if (revealer.reveal(applicationName, className, line)) { + break; + } + } + } } diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/IDebuggerConnector.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/IDebuggerConnector.java new file mode 100644 index 0000000..c50ba30 --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/IDebuggerConnector.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2010 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.ide.eclipse.ddms; + +/** + * Classes which implement this interface provides a way to connect a debugger to a VM running + * on a connected device. + */ +public interface IDebuggerConnector { + + /** + * Connects a debugger to a VM identified by its appName. + * <p/> + * The given port is tied to the application and should be used if possible. However the + * "selected" port can also be used if needed. + * @param appName the name of the application. Usually the application's package but this + * can be different if the component was setup to run in it's own process. + * @param port the preferred connection port. + * @return true if success. + */ + boolean connectDebugger(String appName, int port); + +} diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ISourceRevealer.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ISourceRevealer.java new file mode 100644 index 0000000..18bed4c --- /dev/null +++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/ISourceRevealer.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010 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.ide.eclipse.ddms; + +/** + * Classes which implement this interface are able to open a source file based on the name + * of a running Android application on a connected device. + */ +public interface ISourceRevealer { + + /** + * Sent to reveal a particular line in a source editor + * @param applicationName the name of the application running the source. + * @param className the fully qualified class name + * @param line the line to reveal + * @return true if the source was revealed. + */ + public boolean reveal(String applicationName, String className, int line); + +} 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 f7728f5..f2033de 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 @@ -37,7 +37,7 @@ import com.android.ddmuilib.SyncProgressHelper.SyncRunnable; import com.android.ddmuilib.handler.BaseFileHandler; import com.android.ddmuilib.handler.MethodProfilingHandler; import com.android.ide.eclipse.ddms.DdmsPlugin; -import com.android.ide.eclipse.ddms.DdmsPlugin.IDebugLauncher; +import com.android.ide.eclipse.ddms.IDebuggerConnector; import com.android.ide.eclipse.ddms.preferences.PreferenceInitializer; import org.eclipse.core.filesystem.EFS; @@ -85,7 +85,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien private Action mDebugAction; private Action mHprofAction; private Action mTracingAction; - private IDebugLauncher mDebugLauncher; + private IDebuggerConnector[] mDebuggerConnectors; private ImageDescriptor mTracingStartImage; private ImageDescriptor mTracingStopImage; @@ -246,20 +246,6 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien return sThis; } - /** - * Sets the {@link IDebugLauncher}. - * @param debugLauncher - */ - public void setDebugLauncher(DdmsPlugin.IDebugLauncher debugLauncher) { - mDebugLauncher = debugLauncher; - if (mDebugAction != null && mDeviceList != null) { - Client currentClient = mDeviceList.getSelectedClient(); - if (currentClient != null) { - mDebugAction.setEnabled(true); - } - } - } - @Override public void createPartControl(Composite parent) { mParentShell = parent.getShell(); @@ -377,12 +363,12 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien mTracingAction.setImageDescriptor(mTracingStartImage); // check if there's already a debug launcher set up in the plugin class - mDebugLauncher = DdmsPlugin.getRunningAppDebugLauncher(); + mDebuggerConnectors = DdmsPlugin.getDefault().getDebuggerConnectors(); mDebugAction = new Action("Debug Process") { @Override public void run() { - if (mDebugLauncher != null) { + if (mDebuggerConnectors.length != 0) { Client currentClient = mDeviceList.getSelectedClient(); if (currentClient != null) { ClientData clientData = currentClient.getClientData(); @@ -408,18 +394,23 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien // get the name of the client String packageName = clientData.getClientDescription(); if (packageName != null) { - if (mDebugLauncher.debug(packageName, - currentClient.getDebuggerListenPort()) == false) { - // if we get to this point, then we failed to find a project - // that matched the application to debug - Display display = DdmsPlugin.getDisplay(); - Shell shell = display.getActiveShell(); - MessageDialog.openError(shell, "Process Debug", - String.format( - "No opened project found for %1$s. Debug session failed!", - packageName)); + // try all connectors till one returns true. + for (IDebuggerConnector connector : mDebuggerConnectors) { + if (connector.connectDebugger(packageName, + currentClient.getDebuggerListenPort())) { + return; + } } + + // if we get to this point, then we failed to find a project + // that matched the application to debug + Display display = DdmsPlugin.getDisplay(); + Shell shell = display.getActiveShell(); + MessageDialog.openError(shell, "Process Debug", + String.format( + "No opened project found for %1$s. Debug session failed!", + packageName)); } } } @@ -427,7 +418,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien }; mDebugAction.setToolTipText("Debug the selected process, provided its source project is present and opened in the workspace."); mDebugAction.setImageDescriptor(loader.loadDescriptor("debug-attach.png")); //$NON-NLS-1$ - if (mDebugLauncher == null) { + if (mDebuggerConnectors.length == 0) { mDebugAction.setEnabled(false); } @@ -462,7 +453,7 @@ public class DeviceView extends ViewPart implements IUiSelectionListener, IClien selectedClient.setAsSelectedClient(); } - mDebugAction.setEnabled(mDebugLauncher != null); + mDebugAction.setEnabled(mDebuggerConnectors.length != 0); mKillAppAction.setEnabled(true); mGcAction.setEnabled(true); diff --git a/testapps/basicProject/res/layout/main.xml b/testapps/basicProject/res/layout/main.xml index b79cddb..783e4a0 100644 --- a/testapps/basicProject/res/layout/main.xml +++ b/testapps/basicProject/res/layout/main.xml @@ -7,7 +7,7 @@ <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" - android:text="Hello World, Main" + android:text="Basic Project" /> </LinearLayout> |