From 05e6b1fc1f328fe49603ac741e78d314466bd442 Mon Sep 17 00:00:00 2001
From: Brett Chabot <>
Date: Thu, 2 Apr 2009 15:36:04 -0700
Subject: [PATCH] AI 144320: ADT: Fix debugger launch connection when debugging
Android JUnit BUG=1753089
Automated import of CL 144320
---
.../adt/launch/AndroidLaunchController.java | 12 ++++--
.../ide/eclipse/adt/launch/DelayedLaunchInfo.java | 20 ++++++++-
.../eclipse/adt/launch/LaunchConfigDelegate.java | 7 ++--
.../adt/launch/junit/AndroidJUnitLaunchAction.java | 1 -
.../junit/AndroidJUnitLaunchConfigDelegate.java | 41 ++++++++++++++----
.../junit/AndroidJUnitLaunchConfigurationTab.java | 2 +-
.../junit/InstrumentationRunnerValidator.java | 19 +++++----
.../common/project/AndroidManifestParser.java | 49 ++++++++++++++++++----
.../common/project/AndroidManifestParserTest.java | 16 ++++---
9 files changed, 124 insertions(+), 43 deletions(-)
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
index b6c7640c7..655c038e1 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/AndroidLaunchController.java
@@ -314,6 +314,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* defined by ILaunchManager
- RUN_MODE
or
* DEBUG_MODE
.
* @param apk the resource to the apk to launch.
+ * @param packageName the Android package name of the app
+ * @param debugPackageName the Android package name to debug
* @param debuggable the debuggable value of the app, or null if not set.
* @param requiredApiVersionNumber the api version required by the app, or
* {@link AndroidManifestParser#INVALID_MIN_SDK} if none.
@@ -322,7 +324,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
* @param launch the launch object
*/
public void launch(final IProject project, String mode, IFile apk,
- String packageName, Boolean debuggable, int requiredApiVersionNumber,
+ String packageName, String debugPackageName, Boolean debuggable, int requiredApiVersionNumber,
final IAndroidLaunchAction launchAction, final AndroidLaunchConfiguration config,
final AndroidLaunch launch, IProgressMonitor monitor) {
@@ -331,7 +333,8 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
// create the launch info
final DelayedLaunchInfo launchInfo = new DelayedLaunchInfo(project, packageName,
- launchAction, apk, debuggable, requiredApiVersionNumber, launch, monitor);
+ debugPackageName, launchAction, apk, debuggable, requiredApiVersionNumber, launch,
+ monitor);
// set the debug mode
launchInfo.setDebugMode(mode.equals(ILaunchManager.DEBUG_MODE));
@@ -922,6 +925,7 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
DelayedLaunchInfo delayedLaunchInfo = new DelayedLaunchInfo(
androidProject.getProject(),
manifestParser.getPackage(),
+ manifestParser.getPackage(),
launchInfo.getLaunchAction(),
apk,
manifestParser.getDebuggable(),
@@ -1524,14 +1528,14 @@ public final class AndroidLaunchController implements IDebugBridgeChangeListener
for (int i = 0; i < mWaitingForDebuggerApplications.size(); ) {
final DelayedLaunchInfo launchInfo = mWaitingForDebuggerApplications.get(i);
if (client.getDevice() == launchInfo.getDevice() &&
- applicationName.equals(launchInfo.getPackageName())) {
+ applicationName.equals(launchInfo.getDebugPackageName())) {
// this is a match. We remove the launch info from the list
mWaitingForDebuggerApplications.remove(i);
// and connect the debugger.
String msg = String.format(
"Attempting to connect debugger to '%1$s' on port %2$d",
- launchInfo.getPackageName(), client.getDebuggerListenPort());
+ launchInfo.getDebugPackageName(), client.getDebuggerListenPort());
AdtPlugin.printToConsole(launchInfo.getProject(), msg);
new Thread("Debugger Connection") { //$NON-NLS-1$
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
index 7dae56d00..f3bd28a07 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/DelayedLaunchInfo.java
@@ -44,6 +44,9 @@ public final class DelayedLaunchInfo {
/** Package name */
private final String mPackageName;
+
+ /** Debug package name */
+ private final String mDebugPackageName;
/** IFile to the package (.apk) file */
private final IFile mPackageFile;
@@ -79,7 +82,8 @@ public final class DelayedLaunchInfo {
* Basic constructor with activity and package info.
*
* @param project the eclipse project that corresponds to Android app
- * @param packageName package name of Android app
+ * @param packageName package name of Android app
+ * @param debugPackageName the package name of the Andriod app to debug
* @param launchAction action to perform after app install
* @param pack IFile to the package (.apk) file
* @param debuggable debuggable attribute of the app's manifest file.
@@ -88,11 +92,12 @@ public final class DelayedLaunchInfo {
* @param launch the launch object
* @param monitor progress monitor for launch
*/
- public DelayedLaunchInfo(IProject project, String packageName,
+ public DelayedLaunchInfo(IProject project, String packageName, String debugPackageName,
IAndroidLaunchAction launchAction, IFile pack, Boolean debuggable,
int requiredApiVersionNumber, AndroidLaunch launch, IProgressMonitor monitor) {
mProject = project;
mPackageName = packageName;
+ mDebugPackageName = debugPackageName;
mPackageFile = pack;
mLaunchAction = launchAction;
mLaunch = launch;
@@ -130,6 +135,17 @@ public final class DelayedLaunchInfo {
}
/**
+ * Returns the Android app process name that the debugger should connect to. Typically this is
+ * the same value as {@link getPackageName}
+ */
+ public String getDebugPackageName() {
+ if (mDebugPackageName == null) {
+ return getPackageName();
+ }
+ return mDebugPackageName;
+ }
+
+ /**
* @return the application package file
*/
public IFile getPackageFile() {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
index d057ac709..9f12b16e4 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/LaunchConfigDelegate.java
@@ -306,9 +306,10 @@ public class LaunchConfigDelegate extends LaunchConfigurationDelegate {
// everything seems fine, we ask the launch controller to handle
// the rest
- controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
- manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
- launchAction, config, androidLaunch, monitor);
+ controller.launch(project, mode, applicationPackage,manifestParser.getPackage(),
+ manifestParser.getPackage(), manifestParser.getDebuggable(),
+ manifestParser.getApiLevelRequirement(), launchAction, config, androidLaunch,
+ monitor);
}
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
index 9bcc63d06..24ebe21c0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchAction.java
@@ -63,7 +63,6 @@ class AndroidJUnitLaunchAction implements IAndroidLaunchAction {
try {
mLaunchInfo.setDebugMode(info.isDebugMode());
mLaunchInfo.setDevice(info.getDevice());
- mLaunchInfo.setLaunch(info.getLaunch());
JUnitLaunchDelegate junitDelegate = new JUnitLaunchDelegate(mLaunchInfo);
final String mode = info.isDebugMode() ? ILaunchManager.DEBUG_MODE :
ILaunchManager.RUN_MODE;
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
index 543daf06f..19067921b 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigDelegate.java
@@ -25,6 +25,7 @@ import com.android.ide.eclipse.adt.launch.LaunchConfigDelegate;
import com.android.ide.eclipse.adt.launch.junit.runtime.AndroidJUnitLaunchInfo;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
+import com.android.ide.eclipse.common.project.AndroidManifestParser.Instrumentation;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import org.eclipse.core.resources.IFile;
@@ -60,7 +61,6 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
AndroidLaunchConfiguration config, AndroidLaunchController controller,
IFile applicationPackage, AndroidManifestParser manifestParser) {
- String appPackage = manifestParser.getPackage();
String runner = getRunner(project, configuration, manifestParser);
if (runner == null) {
AdtPlugin.displayError("Android Launch",
@@ -68,19 +68,46 @@ public class AndroidJUnitLaunchConfigDelegate extends LaunchConfigDelegate {
androidLaunch.stopLaunch();
return;
}
- AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project, appPackage,
- runner);
+ // get the target app's package
+ String targetAppPackage = getTargetPackage(manifestParser, runner);
+ if (targetAppPackage == null) {
+ AdtPlugin.displayError("Android Launch",
+ String.format("A target package for instrumention test runner %1$s could not be found!",
+ runner));
+ androidLaunch.stopLaunch();
+ return;
+ }
+ String testAppPackage = manifestParser.getPackage();
+ AndroidJUnitLaunchInfo junitLaunchInfo = new AndroidJUnitLaunchInfo(project,
+ testAppPackage, runner);
junitLaunchInfo.setTestClass(getTestClass(configuration));
junitLaunchInfo.setTestPackage(getTestPackage(configuration));
junitLaunchInfo.setTestMethod(getTestMethod(configuration));
-
+ junitLaunchInfo.setLaunch(androidLaunch);
IAndroidLaunchAction junitLaunch = new AndroidJUnitLaunchAction(junitLaunchInfo);
-
- controller.launch(project, mode, applicationPackage, manifestParser.getPackage(),
+
+ controller.launch(project, mode, applicationPackage, testAppPackage, targetAppPackage,
manifestParser.getDebuggable(), manifestParser.getApiLevelRequirement(),
junitLaunch, config, androidLaunch, monitor);
}
-
+
+ /**
+ * Get the target Android application's package for the given instrumentation runner, or
+ * null
if it could not be found.
+ *
+ * @param manifestParser the {@link AndroidManifestParser} for the test project
+ * @param runner the instrumentation runner class name
+ * @return the target package or null
+ */
+ private String getTargetPackage(AndroidManifestParser manifestParser, String runner) {
+ for (Instrumentation instr : manifestParser.getInstrumentations()) {
+ if (instr.getName().equals(runner)) {
+ return instr.getTargetPackage();
+ }
+ }
+ return null;
+ }
+
/**
* Returns the test package stored in the launch configuration, or null
if not
* specified.
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
index 584d45eb1..34e64e327 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/AndroidJUnitLaunchConfigurationTab.java
@@ -955,7 +955,7 @@ public class AndroidJUnitLaunchConfigurationTab extends AbstractLaunchConfigurat
try {
mInstrValidator = new InstrumentationRunnerValidator(project);
mInstrumentations = (mInstrValidator == null ? null :
- mInstrValidator.getInstrumentations());
+ mInstrValidator.getInstrumentationNames());
if (mInstrumentations != null) {
mInstrumentationCombo.removeAll();
for (String instrumentation : mInstrumentations) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
index f22fc7cda..7ebbb0997 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/launch/junit/InstrumentationRunnerValidator.java
@@ -18,6 +18,7 @@ package com.android.ide.eclipse.adt.launch.junit;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.common.AndroidConstants;
import com.android.ide.eclipse.common.project.AndroidManifestParser;
+import com.android.ide.eclipse.common.project.AndroidManifestParser.Instrumentation;
import com.android.ide.eclipse.common.project.BaseProjectHelper;
import org.eclipse.core.resources.IProject;
@@ -29,7 +30,7 @@ import org.eclipse.jdt.core.IJavaProject;
*/
class InstrumentationRunnerValidator {
private final IJavaProject mJavaProject;
- private String[] mInstrumentations = null;
+ private String[] mInstrumentationNames = null;
private boolean mHasRunnerLibrary = false;
static final String INSTRUMENTATION_OK = null;
@@ -73,7 +74,11 @@ class InstrumentationRunnerValidator {
}
private void init(AndroidManifestParser manifestParser) {
- mInstrumentations = manifestParser.getInstrumentations();
+ Instrumentation[] instrumentations = manifestParser.getInstrumentations();
+ mInstrumentationNames = new String[instrumentations.length];
+ for (int i = 0; i < instrumentations.length; i++) {
+ mInstrumentationNames[i] = instrumentations[i].getName();
+ }
mHasRunnerLibrary = hasTestRunnerLibrary(manifestParser);
}
@@ -94,13 +99,13 @@ class InstrumentationRunnerValidator {
}
/**
- * Return the set of instrumentations for the Android project.
+ * Return the set of instrumentation names for the Android project.
*
* @return null
INSTRUMENTATION_OK if valid, otherwise returns error message
*/
String validateInstrumentationRunner(String instrumentation) {
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
index 85ba96839..f853adacb 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/common/project/AndroidManifestParser.java
@@ -52,6 +52,7 @@ public class AndroidManifestParser {
private final static String ATTRIBUTE_PROCESS = "process"; //$NON-NLS-$
private final static String ATTRIBUTE_DEBUGGABLE = "debuggable"; //$NON-NLS-$
private final static String ATTRIBUTE_MIN_SDK_VERSION = "minSdkVersion"; //$NON-NLS-$
+ private final static String ATTRIBUTE_TARGET_PACKAGE = "targetPackage"; //$NON-NLS-1$
private final static String NODE_MANIFEST = "manifest"; //$NON-NLS-1$
private final static String NODE_APPLICATION = "application"; //$NON-NLS-1$
private final static String NODE_ACTIVITY = "activity"; //$NON-NLS-1$
@@ -77,6 +78,33 @@ public class AndroidManifestParser {
public final static int INVALID_MIN_SDK = -1;
/**
+ * Instrumentation info obtained from manifest
+ */
+ public static class Instrumentation {
+ private final String mName;
+ private final String mTargetPackage;
+
+ public Instrumentation(String name, String targetPackage) {
+ mName = name;
+ mTargetPackage = targetPackage;
+ }
+
+ /**
+ * Returns the fully qualified instrumentation class name
+ */
+ public String getName() {
+ return mName;
+ }
+
+ /**
+ * Returns the Android app package that is the target of this instrumentation
+ */
+ public String getTargetPackage() {
+ return mTargetPackage;
+ }
+ }
+
+ /**
* XML error & data handler used when parsing the AndroidManifest.xml file.
*